Jvm在运行时的内存分区图:
- 方法区:属于线程共享,存储一些已被虚拟机加载的类型信息,静态变量、常量、即时编译器编译后的代码缓存等数据
- 堆:属于线程共享,存储对象实例。
- jvm栈:线程数据不共享,存储一些局部变量,用C/C++概念上来说比如地址、对象句柄等。
- 本地方法栈:这个主要的作用是可以实用到本地的Native方法服务,比如我们说的c/c++的代码等。
- 程序计数器:可以理解为线程中代码的执行行记录器。每个线程都有一个程序计数器来做为程序执行的标记。
书中特地强调了运行时的常量池,通过上面描述可以得知运行时常量池属于方法区的一部分。如果常量池无法申请到内存的时候,自然也会抛出OutOfMemoryError的异常。
直接内存,这里用我的理解是调用了native的方法,属于本地方法栈的一部分内容。比如I/O。
在此不得不说去理解书中一直提到的Eden 和 Survivor的概念。
Eden:初生代 Survivor:幸存者 OldMemory 老年代
个人理解:内存是有限的,如果没有GC进行回收。就会出现内存爆表的现象。为了解决这个问题,GC也就诞生了。
初生代好比我们刚刚出生的状态,在经历第一次的磨练之后,没有气馁。再经过第二次磨练的时候仍然表现出坚强。与此同时,每一年的磨练你的年龄也在+1,达到一定的时间的时候你就进入了老年状态。粗糙点先这样理解。
一个实例对象的诞生地就在Eden(初生代)中,当垃圾回收器Gc执行第一次后,它没有被回收,就会进入第二轮第三轮等N多次的回收,当达到一个阈值的时候,就进入到了老年代。