概述
第二章的标题是:Java内存区域与内存溢出异常
线程私有的
程序计数器
当前线程被重新调度到CPU中执行的时候,为了能恢复到上次的执行位置,需要使用一个计数器。
Java虚拟机栈
栈存储的信息
对象引用和基本类型
生命周期
跟线程一致。当线程结束后,线程执行的方法中定义的局部变量引用所占用的内存将会被释放掉。(注意:不是说堆上面的对象的内存被释放掉,堆上的对象只能默默的等待垃圾回收)
一个线程占用多少栈空间
默认是一兆,也可以使用Xss指定。
小心递归调用的层次
如果递归调用的层数太多,会撑爆栈空间。
为谁服务
为虚拟机执行Java方法服务的。
本地方法栈
跟Java虚拟机栈一样的,只不过本地方法栈是为虚拟机调用Native方法服务的。
备注
程序计数器、Java虚拟机栈、本的方法栈都无需过多的考虑垃圾回收的问题,因为它们都是随着线程生也随着线程死。线程一旦结束,内存也就回收了。
线程共享的
Java堆
堆存储的信息
对象的实例。
方法区(别名:永久代)
方法区存储的信息
- 已经被虚拟机加载的类信息
- 常量
- 静态变量
- 即时编译器编译后的代码
垃圾回收
主要是针对常量池和Class对象的卸载的垃圾回收。
运行时常量池
- 每个Class对象都有一个静态的常量池,当虚拟机加载完类后,会把这个静态常量池的内容存放到运行时常量池中;
- 运行时常量池是方法区的一部分。
总结
以上都是JVM运行时数据区的一部分。
非运行时数据区
直接内存(堆外内存)
像使用了Java NIO、Netty等技术,会大量使用到直接内存,在JAVA中这块内存是通过Native方法来申请的。由于减少了应用到内核的数据拷贝次数,可以提高性能。
当老年代内存满了,触发Full GC的时候,会顺便回收直接内存。当然也可以使用System.gc()
,但是虚拟机会不会触发GC则是未必的。