多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 简单代码的内存分配分析(一) **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)