# 简单代码的内存分配分析(一)
**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 这个数字在代码中,字符串:"小明" 在常量池中。这两块内存分配都不是运行时分配的,在类加载的时候,就已经加载到了内存中
![](https://box.kancloud.cn/0aa93cac0993ae71f0f80a92525fed2c_806x672.png)