Appearance
1、请谈谈你对JVM的理解?
Java语言的一个非常重要的特点就是与平台无关性。而使用JVM是实现这一特点的关键。Java语言编写的源程序通过编译器,就编译成了与平台无关的字节码文件,然后便可以在JVM上运行
2、java8的虚拟机有什么更新?
在
java8中,永久代已经被移除,被一个名为 元空间 的区域所取代。元空间的本质和永久代类似。
元空间和永久代的最大区别?
永久代使用的是
JVM的堆内存,但是元空间 不在虚拟机中而是使用的本机物理内存因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入本地内存,字符串池和类的静态变量放入堆中,这样可以加载多少类的元数据不再有
MaxPermSize控制,而由系统实际可用空间来控制
3、JVM的常用参数调优有哪些?
堆内存调优简介
-Xms 初始分配大小,默认为物理内存的 1/64
-Xmx 最大分配内存,默认为物理内存的 1/4
生产环境中一般将初始分配大小和最大分配内存一样大,避免
GC和其它程序争抢内存
-XX:+PrintGCDetails 输出详细的GC处理细节
-XX:MaxTenuringThreshold 设置对象在新生代中存活的次数,到达该次数对象就会进入老年代(Java8中不能超过15,缺省值为15)
4、GC
GC(Garbage Collection) 是垃圾回收的意思,因为java是动态分配内存大小的,并且依靠垃圾回收机制来完成对分配空间的回收,从而避免内存溢出的问题。
GC一般都采用分代回收算法。
JVM在进行GC时,并非每次都对 young,Old,Perm三个内存区域一起回收,大部分回收的是新生代因此
GC按照回收的区域又分成了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC)
Minor GC和 Full GC的区别
minor GC:只针对新生代区域,指发生在新生代的垃圾收集动作,因为java对象存活率都不高,所以minor GC费用频繁,一般回收速度也快
major GC:指发生在老年代的垃圾收集动作,出现了 major GC,经常会伴随至少一次的 minor GC(但并不是绝对的)。major GC一般比minor GC速度慢十倍以上(major GC空间大)。
4算法
引用计数法(不使用)
缺点:
- 每次对对象赋值时均要维护引用计数器,且计数器本身也有一定的消耗
- 较难处理循环引用
复制算法(Copying)
常见常用方法, 年轻代中使用的是
Minor GC,这种GC算法采用的是复制算法 ,复制算法的基本思想是将内存分为两块,每次只用其中一块,当一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。缺点:耗空间
原理:
- 从根集合开始,通过Tracing从From中找到存活对象,拷贝到To中
- From、To交换身份,下次内存分配从To开始
标记清除(Mark - Sweep)
老年代一般是由标记清除或者是标记清除与标记整理的混合
算法分为标记和清除两个阶段,先标记出要回收的对象,然后统一回收这些对象。
通俗的讲:当程序运行期间,若可以使用的内存被耗尽的时候,
GC线程就会被触发并将程序暂停,随后将要回收的对象标记一遍,最后统一回收这些对象,完成标记清理工作接下来便让应用程序恢复运行。缺点:
- 两次扫描,耗时严重
- 会产生内存碎片(空间内存不连续)
标记压缩(Mark-Compact)
原理:
标记
与 标记-清除一样
压缩
再次扫描,并往一端 滑动存活对象
标记/整理算法的唯一缺点就是 效率不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。
从效率上来说,标记/整理算法低于复制算法。
三种算法的比较
内存效率:复制算法 > 标记清除算法 > 标记整理算法 (此处的效率只是简单的对比时间复杂度)
内存整齐度:复制算法 = 标记整理算法 > 标记清除算法
内存利用率:标记整理算法 = 标记清除算法 > 复制算法
5、MinorGC 的过程 (复制 ··> 清空 ··> 交换)
1. eden、SurvivorForm复制到SurvivorTo,年龄加1
首先,当Eden区满的时候会触发第一次
GC,把还活着的对象拷贝到SurvivorForm区,当Eden区再次触发GC时会对 Eden +survivorForm区进行垃圾回收,经过这次回收还存活的对象,则直接复制到 To区(如果有对象达到老年区的标准,则复制到老年代区),同时把这些对象的年龄+1
2. 清空eden、SurvivorForm
进行
GC的时候回清空eden、survivorForm区中的对象
3. SurvivorForm 和 SurvivorTo互换
最后
survivorForm区和survivorTo区互换,原来的 to区成为下一次GC时的form区。部分对象会在 form和to 区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,默认值为15),最终如果还是存活就存入老年代
6、什么是类装载器ClassLoader?
负责加载class文件,class文件在 文件开头有特定的文件标识 将class文件字节码内容加载到内存中,并将这些内容转换成方法区中运行时数据结构。类装载器只负责class文件的加载,至于它是否可以运行,则有执行引擎决定
虚拟机自带的加载器
- 启动类加载器(Bootstrap)
- 扩展类加载器(Extension)
- 应用程序类加载器(
AppClassLoader)- 用来加载当前应用的
classpath下的所有类
- 用来加载当前应用的
用户自定义加载器
java.lang.ClassLoader 的子类,用户可以定制类的加载方式
什么是双亲委派机制?、
当一个类收到了类加载请求,它首先不会尝试自己其加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载器中,只有当父类加载器在它的加载路径下没有找到所需加载的Class,子类加载器才会去尝试自己去加载。
采用双亲委派的一个好处是,不管使用哪个加载器加载类,最终都会委托给顶层的启动类加载器进行加载,保证了沙箱安全
