JVM虚拟机深入理解+GC回收+类加载

旭日Follow_24 的CSDN 博客 ,全文地址请点击:

https://blog.csdn.net/xuri24/article/details/81455449

一,前言

本文章是读了“深入理解java虚拟机”一书的笔记记录和心得。作为一名Java的开发从业者或爱好者,想要在这条路继续和深入发展下去,了解和熟练掌握JVM虚拟机结构原理是作为技术人员的一项基础能力,掌握的深浅在某个方面衡量了一个技术人员的基本功个编程造诣。

很多时候,我们去掌握一项技术知识,都是从工作中去学习并实践掌握真的印证那句:实践是检验真理的唯一标准!

但是,作为技术人员,想要扎实并深刻的掌握一项技术知识学习的先后顺序应为:。基本原理 - >学会使用 - >实践 - >回顾这样才会把一项技术知识学的透彻并牢固掌握。

二,JVM的基本介绍

Java程序设计语言,java虚拟机,javaApi类库三部分统称为JDK,JDK是用户支持java程序开发的最小环境。把java文件列入javaSe API子集和java虚拟机这两部分统称为JRE, JRE是支持的java程序运行的标准环境。

三,JVM基本结构

JVM虚拟机深入理解+GC回收+类加载JVM虚拟机深入理解+GC回收+类加载

四,运行时数据区域

运行时数据区包括以下部分:

JVM虚拟机深入理解+GC回收+类加载JVM虚拟机深入理解+GC回收+类加载

  • 程序计数器

程序计数器可以简单理解为:程序中每个线程运行时,当前线程所执行的字节码的行号指示器字节码工作时,通过这个计数器的值来选取下一条需要执行的字节码指令。分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。每个线程的指令计数器独立互不影响。

  • Java的虚拟机栈

Java的虚拟机栈,是程序运行时,每个Java的方法创建的一个单独私有栈桢用以存储:。局部变量表,操作数栈,动态链接,方法出口灯信息每个方法从调用到执行完成,就对应着一个栈桢在虚拟机中从入栈到出栈的过程局部变量表存放了包括编译器产生的各种基本的java数据类型:布尔,字节,字符,短型,整型,浮点型,长,双等。它是一个对象引用,即指向对象起始地址的引用指针。

  • 本地方法栈

跟虚拟机栈类似,虚拟机栈存放的是为Java的方法服务的栈桢,而本地方法栈存放的是为虚拟机本身使用到的本地方法,可以理解为JDK加载时,调用JRE类库里面的本机方法所用到的栈桢。

  • Java的堆

java堆(Java Heap),是java虚拟机所管理的内存中最大的一块。是被所有线程共享的一块内存区域,在虚拟机启动时创建。唯一目的是:存放所有对象实例.java堆也是垃圾收集管理的主要区域(GC堆)。新生代,老年代/伊甸园,从幸存者空间,到幸存者空间等。

通常的Java堆是物理上不连续的内存空间,逻辑上连续的。类似磁盘空间,可以固定大小,也可以可扩展大小的。-XMX和-Xms控制等。

  • 方法区

方法区跟java的堆一样,各个线程共享的内存区域,它用于存放已经被虚拟机加载的类信息,常量,静态变量,即时编译的代码等数据。

这部分也是GC堆回收到的内存区域只是这部分,是比较难以回收到的区域,可类似看做:。永久代如常量池的回收和类型的卸载之类的工作。

  • 运行时常量池

运行时常量池是方法区的一部分,类文件中除了有类的版本,字段,方法,接口等描述信息外,还有一些是常量池,用于存放编译期间生成的各种字面量和符号引用。这部分内容将在类加载后进入方法区的运行时常量池中存放。

  • 直接内存

直接内存,并不是虚拟机运行时数据区的一部分也不是Java的虚拟机的内存区域可以简单理解为:。程序运行时的工作内存。

五,类加载机制

JVM虚拟机深入理解+GC回收+类加载JVM虚拟机深入理解+GC回收+类加载

  • 加载

加载是“类加载”过程的一个阶段,这个阶段虚拟机需要完成以下三个事情:

1.通过一个类的全限定名来获取定义此类的二进制字节流。

2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3.在内存中生成一个代表这个类的java的,lang.Class对象,作为方法区这个类的各种数据的访问入口。

  • 验证

验证是连接阶段的第一步,这一阶段的目的是为了确保类文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

有如下验证:

1.文件格式验证,验证字节流是否符合类文件格式的规范,并且能够被当前版本的虚拟机处理如:主次版本号是否在当前虚拟机处理范围之内;常量池的常量中是否有不被支持的常量类型;类文件中各个部分及其文件本身是否有被删除的或附加的信息。

2.元数据验证,对字节码描述的信息进行语义分析,以保证其描述的信息符合的Java语言规范的要求,这个阶段可能包括:这个类是否有父类(除了java.lang.Object继承外,其他类都应有父类),这个类的父类是否继承了不允许被继承的类,这个类是不是抽象类,是否实现了其父类或接口之中要求实现的所有方法。

3.字节码验证,验证过程中最复杂的一个阶段,主要通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的。对元数据信息中的数据类型做完校验后,这个阶段会对类的方法体进行校验分析,保证被校验类的方法在运行时不会做出危害虚拟机安全的事件。

4.符号引用验证,验证阶段最后步骤是发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接的第三阶段 - 解析阶段中发生符号引用验证可以看做是对类自身以外的信息进行匹配性校验。

  • 准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配注意是给变量分配初始值,区分:无最后普通变量定义准备阶段后,初始值为数据类型零值。当有最后的修饰的变量,准备阶段后该变量的初始值为定义的初始值。

  • 解析

。解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程包括如下内容:

1.类或接口的解析。

2.字段解析

3.类方法解析

4.接口方法解析

  • 初始化

初始化时类加载过程的最后一个阶段,前面阶段都是由虚拟机主导和控制,加载类的过程(除了用户自定义类加载器外)。初始化阶段,是执行类中定义的Java的程序代码(字节码)。

  • 类加载器

JVM虚拟机深入理解+GC回收+类加载JVM虚拟机深入理解+GC回收+类加载

双亲委派模型,JAVA虚拟机存在两种不同的类加载器:

1.启动类加载器(Bootstrap ClassLoader),这个是虚拟机自身的一部分。通常虚拟机启动的时候,加载自身的一些类库的时候,也会由这个类加载器加载。

2.另外的是独立于虚拟机外的加载器,都继承自(java.lang.ClassLoader的)抽象类加载器。

从开发人员角度来看更细区分,而ClassLoader还分为:扩展类加载器(Extenxion ClassLoader)由sun.misc.Launcher&ExtClassLoader,负责加载<JAVA_HOME> \ lib \ ext目录中或被java.ext.dirs变量所指定路径中的所有类库,开发者可以直接使用扩展类加载器。

应用程序类加载器(Application ClassLoader),由sun.misc.Launcher和AppClassLoader实现。同时这个类是ClassLoader中的getSystemClassLoader()方法的返回值,一般称为系统类加载器。负责加载用户类路径(ClassPath)上指定的类库,开发者可以直接使用这个类加载器。

六,GC垃圾收集器

(1)垃圾收集算法

由于垃圾收集算法的实现涉及大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同,简单介绍几种垃圾收集算法。

  • 标记 - 清除算法

最基础的收集算法是“标记 - 清除”算法,首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

JVM虚拟机深入理解+GC回收+类加载JVM虚拟机深入理解+GC回收+类加载

  • 复制算法

将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已经使用的内存空间一次清理掉。

JVM虚拟机深入理解+GC回收+类加载JVM虚拟机深入理解+GC回收+类加载

  • 标记 - 整理算法

复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会降低与“标记 - 清除”。算法一样,后续步骤不是直接对可回收对象进行清理,而是把所有存活对象都向一端移动。然后直接清理掉端边界以外的内存。

JVM虚拟机深入理解+GC回收+类加载JVM虚拟机深入理解+GC回收+类加载

  • 分代收集算法

这种算法的思想是:把Java的堆分为新生代和老年代,这样就可以根据各个年代的特点采用适当的收集算法新生代每次垃圾回收都有大批对象死去,只有少量存活,采用复制。算法老年代因为对象存活率高,没有额外的空间对它进行分配担保,必须采用“标记 - 清除”或“标记 - 整理”算法来进行回收。

(2)垃圾收集器

垃圾收集器就是内存回收的具体实现,为收集算法的内存回收方法提供具体实现。

  • 串行收集器

串行收集器是最基本的历史最悠久的收集器,是一个单一线程的收集器意思是:。当它在工作时,进行垃圾收集时其他所有工作线程必须暂停服务知道它收集结束有个优点是:当为他专门开一个线程来进行垃圾收集的时候,可以获得最高的单线程收集效率。

  • PARNER收集器

ParNew收集器,是串行收集器的多线程版本,使用了多条线程进行垃圾收集而且可以进行参数控制(-XX:SurvivorRatio / -XX:PretenureSizeThreshold等),但是收集算法,对象分配规则,回收策略等都与串行相同。

  • Parallel Scavenge收集器

是一个新生代收集器,也是使用复制算法的收集器。又是并行的多线程收集器。特点是:可控制的吞吐量:吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)。高吞吐量以为着高效的利用了CPU时间。

  • Serial Old收集器

它是串行收集器的老年代版本,同样是一个单线程收集器使用“标记 - 整理”算法。

  • 并行旧收集器

它是Parallel Scavenge收集器的老版年代本,使用多线程和“标记 - 整理”算法。

  • CMS收集器

是一种以获取最短回收停顿时间为目标的收集器目前很大一部分的Java应用集中在互联网站或者B / S系统的服务器上,这类应用尤其重视服务器的相拥速度应用“标记。 - 清除“算法。

  • G1收集器

它是目前收集器技术发展最前沿的成果之一:

并行与并发

分代收集

空间整合

可预测的停顿

七,虚拟机性能调优

上一篇:反编译.NET工程


下一篇:#1048 Longest String Chain