JVM和GC

java和c++之间有一堵有动态内存分配和垃圾回收技术所围成的高墙。

1.JVM内存模型

总的来说,java虚拟机的内存区域(运行时数据区域)划分分为以下几个区域:

1,程序计数器(PC)

2,java栈(java虚拟机栈)

3,本地方法栈

4,java堆(gc堆)

5,方法区

其中前三是线程私有(隔离)的,后二者是线程共享的。它们各自具有的作用和特征如下:

1.程序计数器(PC):

——可看作当前线程所执行的字节码的行号指示器。分支,循环,挑战,异常处理,线程恢复等都需要这个计数器来完成

——线程私有

——如果线程执行的是一个java方法,这个计数器记录就是字节码地址;如果线程执行的是Native方法,则为空(Undefined)

——较小的内存空间,唯一没有规定OutOfMemoryError的区域

2.java虚拟机栈:

——描述的是java方法执行的内存区域,每个方法都会创建一个栈帧(Stack Frame)用于存储局部变量表、操组数栈、动态链接和方法出口。

——局部变量表存放基本数据类型(boolean、byte、char、short、int、long、float、double)、对象引用和returnAddress类型。在编译时期完成分配,运行不改变其大小。

——线程私有,与线程生命周期相同

3.本地方法栈:

——与java栈十分相似,是为Native方法服务。有的虚拟机实现的时候会将二者合而为一。

4.java堆:

——虚拟机中管理内存最大的一块。存放对象实例和数组。

——是垃圾回收的主要区域,也叫作GC堆。

——线程共享的java堆中可分出多个线程私有的分配缓冲区(Tread Local Allocation Buffer,TLAB)

5.方法区

——线程共享区域,用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。

——逻辑上是java堆的一部分,有个别名“Non-Heap”;

——这部分也是垃圾回收的对象“永久代”,但是效果不好。主要针对常量池的回收和对类型的卸载

——运行时常量池(Runtime Constant Pool)是方法区的一部分,用于存放编译时期生成的各种字面量和符号引用。运行时也可以将新的常量放入池中,String的intern()方法

还有一块不是属于虚拟机运行时数据区的一部分,叫做直接内存(Direct Memory),jdk1.4之后是通过NIO类,引入一种基于通道和缓冲区的I/O方式,通过java堆中的DirectByteBuffer作为这块内存的引用进行操作。

2.垃圾回收原理

1.仅针对java堆和方法区(永久代)的内存区域

2.判断对象是否己死:

——引用计数法:不能解决循环引用的问题

——可达性分析(Reachability Analysis):通过GC Roots对象作为起始点,当一个对象到达GC Roots没有引用链时,表示该对象不可用了。这是现代主流的实现原理

3.当不可达时,处于“缓刑”阶段,至少经历两次标记阶段。一是判断是否有必要执行finalize()方法,如果有必要执行,则放在在F-Queue队列中进行二次标记。如果没有没有覆盖finalize方法或者finalize方法被调用过一次,则说明没有必要执行。

4.回收方法区(永久代)。主要回收废弃常量和无用的类。

5.垃圾回收算法:

猜你喜欢

转载自blog.csdn.net/sinat_28520127/article/details/81091995