1、JVM的位置
Jvm在操作系统之上,是一个软件。在JRE之中。
2、JVM的体系结构
类装载器
-
类装载器的作用:加载class文件
-
类加载的流程:
-
类加载器的类别
1、虚拟机自带的加载器
2、启动类(根)加载器
3、扩展类加载器
4、应用程序加载器
-
双亲委派机制
1、类加载收到类加载的请求
2、将类加载的请求向上委托给上一级类加载器去完成。一直向上委托直到启动类加载器
3、启动类加载器检查是否能够加载这个类,如果不能加载,则委托给下一级类加载器加载。
运行时数据区
1.方法区:是被所有线程共享的,所有字段和方法字节码,以及一些特殊方法。例如:构造函数 接口代码等,所有定义方法信息都保存在该区域,属于共享区域。静态变量、常量、类信息(构造方法、接口定义),运行时常量池都存在于方法区中。
2.栈:栈内存主管程序的运行,生命周期与线程同步。线程结束,栈内存也就释放了。8大基本类型、对象的引用、实例的方法都存在于栈中
3.堆:一个JVM只有一个堆内存,堆内存可以调节。创建对象是在堆中创建。
4.本地方法栈:调用本地方法接口(JNI),JNI的作用是扩展Java的使用,融合不同的编程语言。
5 .程序计数器:每一个线程都有一个程序计数器,是线程私有的,就是一个指针。
GC垃圾回收主要在方法区和堆中
3、堆内存
伊甸园区:所有的对象都是在此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算法
- 引用计数法
给每一个对象增加一个计数器,记录对象使用的次数,用的少的会被回收
- 复制算法
1、每一次GC后伊甸园区存活的对象都会转移到幸存者区,伊甸园区变空
2、幸存者to区永远是空的。伊甸园区和幸存者from区进行了GC后,两个区存活的对象都会转移到幸存者to区中。这个时候幸存者to区变为幸存者from区,幸存者from区变为幸存者to区。
3、若一个对象经历了15次GC后还存活着就进入养老区。
优点:没有内存碎片:没有把东西乱放
缺点:浪费了一本的空间,to区一直为空
所以适用在对象存活度较低的区域,其实就是新生区!
- 标记清除算法
第一次扫描 对有用的对象进行标记(实线代表标记对象)
第二次扫描 清除没有标记的对象
缺点 :浪费时间,扫描了两次,产生了碎片空间
优点:没有浪费空间
- 标记清除压缩
在标记清除算法之后,在进行第二次扫描清除对象后,存在内存碎片,再进行第三次扫描对内存进行压缩,使其成为连续的内存片段。
缺点:浪费时间,扫描了三次
优点:没有浪费空间
优化:可以多进行几次标记清除算法,再进行内存压缩。
6、总结
没有最优的算法,要么时间换空间,要么空间换时间。可以使用分代垃圾回收算法。
新生区:存活率低,使用复制算法 养老区:存活率高,使用标记清除+标记压缩