2.1概述
略
2.2 运行时数据区域
1、程序计数器(线程私有)
2、java虚拟机栈(线程私有)
3、本地方法栈(HotSpot将其与虚拟机栈合二为一)
4、方法区(线程共享):
5、java堆(线程共有):垃圾收集器管理的主要区域,有时也称作为GC堆。
6、运行时常量池
7、直接内存:DirectByteBuffer。
查看自己虚拟机版本
cmd–》java -version
2.3.1对象创建
为新生对象分配内存:
1、指针碰撞():假设java堆中的内存是绝对规整的
2、空闲列表():假设java对中的内存是不规整的
选择哪种分配方式有java堆是否规整决定,但是堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
在划分空间之外,对象创建是个频繁的行为,仅只修改指针是可能会引发线程安全问题,因而解决方案有:
1、对内存分配采用同步机制–CAS配上失败重试的方法
2、把内存分配按照线程划分在不同空间上进行,为每个线程在java堆中分配一块空间,成为本地线程分配缓冲区(TLAB),当使用完分配新的tlab时才进行同步机制锁定。是否使用tlab由:-XX:+/-UseTLAB
内存分配完成之后,初始化被分配的内存区域(不包括对象头?),如果是采用TLAB的方式,可以再分配TLAB的时候完成初始化,以保证对象实例字段不初始化也是可用的。
对对象进行必要设置,这些信息存放在对象头中。
一般来说,完成new后,接着来时init
2.3.2对象的内存布局
1、对象在内存中存储的区域可分为:实例数据、对象头、对齐填充。
2、对象头中存储两部分信息
1)、类型指针,即对象指向他的类元数据,告诉虚拟机对象属于哪个类
2)、存储对象自身运行时数据。gc分代年龄、哈希吗、锁状态、线程持有锁、偏向线程ID、偏向时间戳等。称为“mark word”是非固定的数据结构。
3、实例数据:存储对象真正的数据,也就是程序中定义的各字段内容。包括父类、子类的字段内容。存储顺序会受定义顺序和分配策略参数影响(FieldsAllocationStyle),HotSpot中默认为longs/doubles,ints,shorts/chars,bytes/bolleans,oops。相同宽度的字段总是被分配在一起,满足前提下父类字段会在子类字段之前,如果CompactFields设置为true时,子类字段有可能穿插在父类中。
4、对齐填充不是必然的。
2.3.3 对象的访问定位
1、建立了对象后,依据java栈中本地变量表中的reference数据来操作堆上的具体对象。reference类型是一个指向对象的引用,但并没有定义这个引用以何种方式去定位。
2、主流采用两种方式实现reference的定位:
1)、句柄。在堆中维护一个句柄池(其中包含对象实例数据指针和对象类型数据指针。),在reference保存着对象的句柄地址。优点在于reference中存储的是稳定的句柄地址,对象改变时只要改变句柄池中的对象位置。
2)、直接定位。在reference中存储的是堆中对象的直接位置,在对象中存储的有对象类型数据指针。优点在于速度快。节省了一次指针定位开销。(HotSpot采用)
2.4实战
1、安装eclipse memory analyzer
http://jingyan.baidu.com/article/495ba84106ba5238b30edecc.html
http://www.cnblogs.com/dennyzhangdd/p/5647469.html
我的是win7,参考着两个,当你找不到的时候你就搜索”Memory Analyzer“和”Memory Analyzer(Charts)“
2、讲堆的最小值-Xms和-Xmx设置为一样即可避免自动扩展
==============先到这儿,我要打电话