第一章 内存分配
1. 内存区域。
方法区和堆(线程共享),程序计数器 , VM栈 和 本地方法栈(线程隔离)。
1) java虚拟机栈:线程私有。描述的是java方法执行的内存模型:栈帧,用户存储 局部变量表,操作数栈,动态链接,方法出口等信息。
局部变量表在编译时即可完全确定!如果线程请求的栈深度大于 规定的深度,StackOverflowError.
2) 本地方法栈,类似。
3)堆:垃圾收集器管理的主要区域。线程共享。
4)方法区: 各个线程共享。存储:加载的类信息,常量,静态变量,即时编译后的代码数据。习惯称作:永久待。可以不选择垃圾回收(特殊情况有必要)。
运行时常量池(属于方法区),编译时期的字面量和符号引用。运行期间可以将新的常量放入常量池:String.intern() 方法。
‘
2. 对象创建
1) new的执行: 首先,能否定位到一个类的符号引用,这个符号引用代表的类是否已被加载、解析和初始化。通过后,为新生对象分配内存,内存大小在类加载完后可确定。内存分配有两种方式:指针碰撞和空闲列表。
对象头:这个对象是哪个类的实例,如果找到类的元数据信息,对象的哈希码,GC分代年龄等。
最后一步是init,按照程序员的意愿进行初始化。
2) 对象的内存分布:对象头,实例数据,和对齐填充。
3)对象访问的两种方式:句柄访问 和 直接指针访问。栈中存放 reference引用
3. 栈溢出
1)如果线程请求的栈深度大于虚拟机所允许的最大深度,StackoverflowError
2)如果虚拟机在扩展栈时无法申请足够内存,则 OutofMemoryError
JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。
threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"-Xss is translated in a VM flag named ThreadStackSize”