Skip to content

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按照回收的区域又分成了两种类型,一种是普通GCminor GC),一种是全局GC(major GC or Full GC)

Minor GCFull GC的区别

minor GC:只针对新生代区域,指发生在新生代的垃圾收集动作,因为java对象存活率都不高,所以minor GC费用频繁,一般回收速度也快

major GC:指发生在老年代的垃圾收集动作,出现了 major GC,经常会伴随至少一次的 minor GC(但并不是绝对的)。major GC一般比minor GC速度慢十倍以上(major GC空间大)。

4算法
  1. 引用计数法(不使用)

    缺点:

    • 每次对对象赋值时均要维护引用计数器,且计数器本身也有一定的消耗
    • 较难处理循环引用
  2. 复制算法(Copying)

    常见常用方法, 年轻代中使用的是 Minor GC,这种GC算法采用的是复制算法 ,复制算法的基本思想是将内存分为两块,每次只用其中一块,当一块内存用完,就将还活着的对象复制到另外一块上面。

    复制算法不会产生内存碎片缺点:耗空间

    原理:

    • 从根集合开始,通过Tracing从From中找到存活对象,拷贝到To中
    • From、To交换身份,下次内存分配从To开始
  3. 标记清除(Mark - Sweep)

    老年代一般是由标记清除或者是标记清除与标记整理的混合

    算法分为标记和清除两个阶段,先标记出要回收的对象,然后统一回收这些对象

    通俗的讲:当程序运行期间,若可以使用的内存被耗尽的时候,GC 线程就会被触发并将程序暂停,随后将要回收的对象标记一遍,最后统一回收这些对象,完成标记清理工作接下来便让应用程序恢复运行。

    缺点:

    • 两次扫描,耗时严重
    • 会产生内存碎片(空间内存不连续)
  4. 标记压缩(Mark-Compact)

    原理:

    1. 标记

      标记-清除一样

    2. 压缩

      再次扫描,并往一端 滑动存活对象

    标记/整理算法的唯一缺点就是 效率不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。

    从效率上来说,标记/整理算法低于复制算法。

三种算法的比较

内存效率:复制算法 > 标记清除算法 > 标记整理算法 (此处的效率只是简单的对比时间复杂度)

内存整齐度:复制算法 = 标记整理算法 > 标记清除算法

内存利用率:标记整理算法 = 标记清除算法 > 复制算法

5、MinorGC 的过程 (复制 ··> 清空 ··> 交换)

1. edenSurvivorForm复制到SurvivorTo,年龄加1

首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorForm区,当Eden区再次触发GC时会对 Eden + survivorForm区进行垃圾回收,经过这次回收还存活的对象,则直接复制到 To区(如果有对象达到老年区的标准,则复制到老年代区),同时把这些对象的年龄+1

2. 清空edenSurvivorForm

进行GC的时候回清空 edensurvivorForm区中的对象

3. SurvivorFormSurvivorTo互换

最后 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,子类加载器才会去尝试自己去加载。

采用双亲委派的一个好处是,不管使用哪个加载器加载类,最终都会委托给顶层的启动类加载器进行加载,保证了沙箱安全