JVM

83 阅读4分钟

1、JVM的位置

Jvm在操作系统之上,是一个软件。在JRE之中。

2、JVM的体系结构

image.png

类装载器

  • 类装载器的作用:加载class文件

  • 类加载的流程:

image.png

  • 类加载器的类别

    1、虚拟机自带的加载器

    2、启动类(根)加载器

    3、扩展类加载器

    4、应用程序加载器

  • 双亲委派机制

    1、类加载收到类加载的请求

    2、将类加载的请求向上委托给上一级类加载器去完成。一直向上委托直到启动类加载器

    3、启动类加载器检查是否能够加载这个类,如果不能加载,则委托给下一级类加载器加载。

运行时数据区

1.方法区:是被所有线程共享的,所有字段和方法字节码,以及一些特殊方法。例如:构造函数 接口代码等,所有定义方法信息都保存在该区域,属于共享区域。静态变量、常量、类信息(构造方法、接口定义),运行时常量池都存在于方法区中。

2.栈:栈内存主管程序的运行,生命周期与线程同步。线程结束,栈内存也就释放了。8大基本类型、对象的引用、实例的方法都存在于栈中

3.堆:一个JVM只有一个堆内存,堆内存可以调节。创建对象是在堆中创建

4.本地方法栈:调用本地方法接口(JNI),JNI的作用是扩展Java的使用,融合不同的编程语言。

5 .程序计数器:每一个线程都有一个程序计数器,是线程私有的,就是一个指针。

GC垃圾回收主要在方法区和堆中

3、堆内存

image.png

伊甸园区:所有的对象都是在此new出来的。

幸存者区:当伊甸园区的对象经过GC后存活下来的对象回到幸存者区。

养老区:当一个对象经历过15次GC后还没死,就进入养老区。

永久区:常驻内存,用来存放JDK自身携带的class对象。Interface元数据,存储的是Java运行时的一些环境或者类信息。这个区域不存在垃圾回收,关闭JVM就会释放这个区域的内存

GC垃圾回收主要存在于伊甸园区和养老区

对象进入养老区的GC垃圾回收次数可以调节 -XX:MaxTenuringThreshold = 15;默认是15,可以根据对象调用的次数进行调优!

4、三大JVM

1、Sun公司 HotSport(一般是这个)

2、BEA JRockit

3、IBM J9VM

5、GC垃圾回收机制

JVM在进行垃圾回收时,并不是对新生区和养老区统一回收。

GC的类型

  • 轻GC(普通GC):在Eden满的时候会触发
  • 重GC(全局GC):在养老区满的时候会触发,或者自己 使用 System.gc这样程序可以进行

GC算法

  • 引用计数法

image.png

给每一个对象增加一个计数器,记录对象使用的次数,用的少的会被回收

  • 复制算法

image.png

1、每一次GC后伊甸园区存活的对象都会转移到幸存者区,伊甸园区变空

2、幸存者to区永远是空的。伊甸园区和幸存者from区进行了GC后,两个区存活的对象都会转移到幸存者to区中。这个时候幸存者to区变为幸存者from区,幸存者from区变为幸存者to区。

3、若一个对象经历了15次GC后还存活着就进入养老区。

优点:没有内存碎片:没有把东西乱放

缺点:浪费了一本的空间,to区一直为空

所以适用在对象存活度较低的区域,其实就是新生区

  • 标记清除算法

第一次扫描 对有用的对象进行标记(实线代表标记对象)

image.png

第二次扫描 清除没有标记的对象

image.png

缺点 :浪费时间,扫描了两次,产生了碎片空间

优点:没有浪费空间

  • 标记清除压缩

在标记清除算法之后,在进行第二次扫描清除对象后,存在内存碎片,再进行第三次扫描对内存进行压缩,使其成为连续的内存片段。

image.png

缺点:浪费时间,扫描了三次

优点:没有浪费空间

优化:可以多进行几次标记清除算法,再进行内存压缩。

6、总结

没有最优的算法,要么时间换空间,要么空间换时间。可以使用分代垃圾回收算法。

新生区:存活率低,使用复制算法 养老区:存活率高,使用标记清除+标记压缩