# 簡單代碼的內存分配分析(一)
**Code**
```java
public class Demo {
public static void main(String[] args) {
Person xm = new Person();
xm.age = 10;
xm.name = "小明";
}
}
class Person {
int age;
String name;
}
```
**第一個問題:請分析下下面這段代碼,main方法執行時的內存分配情況**
基本分析如下:
1. PC 計數器指向code,PC計數器是**線程獨立**的
2. 方法區是線程間共享的,包括代碼 和 常量池
3. 堆是線程共享的,對Java來說,可以認為所有的對象都分配在堆上(部分JVM實現有可能會優化為棧上分配,類似c的結構體)
4. age 是基本變量,Person.age 存儲直接值:10(int,四個字節)
5. name 是指針,指向方法區的 "小明"
6. 指針大小是和機器字長有關系,一般32位機器上是4個字節,64位機器上,8個字節(因為要尋址到全部的內存)
7. 一個對象除了成員變量外,一般還會有 對象頭和 padding
8. padding用來內存對齊,提高執行效率。(思考問題:為什么普遍存在字節對齊)
9. 對象頭存儲一些JVM實現需要的數據,例如:
* 對象鎖類型(Hotspot上,鎖是逐步升級的)
* 對象的分代年齡
* 對象的class指針等等
10. **一個對象的成員變量之間,在堆上是連續的內存空間**,不同對象之間在堆上有可能連續,有可能不連續
11. 棧是函數調用形成的,**線程獨有**,每個線程有自己的棧;每次方法調用就壓入一個棧幀,方法返回就pop一個棧幀
12. 對基于棧的虛擬機(Dalvik和ART是基于寄存器的,Hotspot和其他大部分虛擬機是基于棧的)每個棧幀里面至少有四方面信息:
* 變量數組,包括傳入的參數,局部變量,如果是成員方法調用的化,還有this指針
* 操作數棧,用來執行code以及存儲中間數據,這個操作數棧也是基于棧的虛擬機egine core。
* 指向常量池的指針
* 返回值地址
13. 整形: 10 這個數字在代碼中,字符串:"小明" 在常量池中。這兩塊內存分配都不是運行時分配的,在類加載的時候,就已經加載到了內存中
