- jvm有哪些主要组成部分及其作用
jvm主要组成部分包括:类加载器、运行时数据区(内存结构)、执行引擎、本地接口库、垃圾回收机制。
java程序运行时,首先通过类加载器把Java代码转换成字节码。然后运行时数据区再把字节码加载到内存中,而字节码文件只是JVM的一套指令集规范,并不能直接交给底层操作系统去执行。需要特定的执行引擎,将字节码翻译成底层系统指令,再交由CPU去执行。在此过程中还需要通过本地接口库调用其他语言来实现整个程序的功能。在此过程中垃圾回收机制会将一些不需要的内存释放回收,避免出现内存溢出等问题。
什么是解释执行什么是编译执行
jvm执行引擎有两种执行方式,分别是解释执行和编译执行。jvm执行引|擎采用两种方式结合使用。
解释执行:将字节码一行一行的翻译成机器码执行,响应速度快。
编译执行:将一些热点代码二次编译成机器码存贮,当再次遇到热点代码,不需要编译,直接调用机器码运行。执行效率高。什么是双亲委派模型
在jvm中有很多类加载器,双亲委派模型要求除了顶层的启动类加载器外,每个类加载器都要有一个父类加载器。当类加载器接收到类加载请求后,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就由父类加载器加载。倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。
优点:
1.在多线程的情况下可以避免一个类被重复加载。
2.保护程序安全,防止核心类被随意篡改。
- 介绍一下jvm的内存结构
jvm的内存结构就是运行时数据区,包括Java栈、Java堆、方法区、本地方法栈、程序计数器。
方法区:线程间共享。存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等,也叫永久代。
Java堆:线程间共享。java内存最大的一块,所有对象实例、数组都存放在java堆,垃圾回收主要的地方。堆内存分为新生代和老年代,默认内存比例是1:2。新生代又分为一个eden区和两个survivor区,内存比为8:1:1。new出来的对象先放在eden中,当经历一次minor GC后会从eden转移到survivor中,每经历一次垃圾回收,对象的年龄就会加1,经过多次垃圾回收还存活的对象会转移到老年代(默认15次)。如果new的对象很大,eden内存不够,则直接放入老年代。
Java栈:线程私有。存放基本数据类型、对象的引用、方法出口等。
本地方法栈:线程私有。和虚拟栈相似,只不过它服务于Native方法。
程序计数器:线程私有。当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址。
- 垃圾回收机制如何确认对象是否需要回收
1.引用计数法:对象的引用为0时回收。缺点是循环引用的对象无法回收,jvm没有使用该方法。
2.可达性分析法:通过一系列称为GC Roots的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称.为引用链,当一个对象到GC Roots没有任何引用链(即GC Roots到对象不可达)时,则证明此对象是不可用的。对不可用对象做一个标记。对于可达性分析而言,被标记不一定意味着被清理。当第一次标记后,若发现该对象的finalize方法被重写且没有被执行过,则将该对象加入F_Queue的队列中,若finalize方法执行过后还没有关联上,那再进行标记,就被回收。jvm采用该方法。
- 根据回收区域的不同垃圾回收机制分为哪几类
1.minor GC:用于清理新生代,速度较快。
2.major GC:用于清理老年代。
3.full GC:清理整个堆空间,成本较高,对系统性能产生影响。
以上三种只是俗称,比如major GC和full GC有时容易混淆,具体还要根据相应的垃圾回收器是哪种。
- 垃圾回收算法有哪些
1.标记清除算法:分两步,第一步将需要清理的内存空间标记,第二步将其清理。
优点:简单。
缺点:效率不高,且容易造成内存碎片,导致大对象无法存储。
2.复制算法:将内存分为两块,一块用于使用,一块用于复制存活对象。优点:解决标记清理效率低的问题,减少内存碎片。缺点:内存利用率只有一半。minor GC一般都采用该算法。
3.标记-整理算法:先将需要清理的内存空间标记,让存活对象向一端移动,最后统一回收。优点:解决复制算法内存利用率低的问题吗,减少内存碎片。缺点:增加了存活对象移动的开销。major GC一般采用该算法。
4.分代算法:以上算法的组合使用,针对新生代和老年代选用不同算法,提高效率。full GC一般采用该算法。
- 常见的垃圾回收器有哪些
1.Serial:串行运行,作用于新生代。使用复制算法,响应速度优先,适用于单CPU环境下的client模式。
2.ParNew:并行运行,作用于新生代。使用复制算法,响应速度优先,多CPU环境Server模式下与CMS配合使用。
3.Parallel:并行运行,作用于新生代。使用复制算法,吞吐量优先,适用于后台运算而不需要太多交互的场景。
4.Serial Old:串行运行,作用于老年代。使用标记-压缩算法,响应速度优先,适用于单CPU环境下的Client模式。
5.Parallel Old:并行运行,作用于老年代。使用标记-压缩算法,吞吐量优先,适用于后台运算而不需要太多交互的场景。
6.CMS:并发运行,作用于老年代。使用标记清除算法,响应速度优先,适用于互联网或B/s业务。
7.G1:并发、并行运行,作用于新生代、老年代。新生代使用复制算法,老年代使用标记-压缩算法。响应速度优先,适合面向服务端应用。
- jvm内存新生代中为什么要分为eden和survior?
1如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC.老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多。Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历15次MinorGC还能在新生代中存活的对象,才会被送到老年代。
2.设置两个Survivor区最大的好处就是解决了碎片化,方.便使用复制算法。
- 垃圾回收机制的工作流程
当新生代eden空间不足时,触发一次minor GC,将eden中存活的对象和使用中的survivor存活的对象复制到另一个suivivor中,同时把一些超年龄的放入老年代。若还不够,把一些活跃的对象从eden放入survivor中。若还不够,放入老年代。若老年代不够,触发一次majorGC/fullGC,若不够,抛出内存不足的异常。
JVM调优的目的就是尽量减少major GC/full GC的次数。
- jvm常用的调优参数有哪些
- Xms:初始化堆内存大小,默认为物理内存的1/64(小于1GB)。例如:-Xms512M。
- Xmx:堆内存最大值。
- Xmn:新生代大小,包括Eden区与2个Survivor区。
- Xss:指定线程栈大小。例如:-Xss128K.
- XX:NewRatio=n:设置老年代和新生代的比值,n为老年代新生代,默认为2。
- XX:SurvivorRatio=n:设置Eden区与一个Survivor区比值,n为eden/survivor,默认为8。
- XX:MaxTenuringThreshold=n:设置新生代需要经历多少次GC才能晋升到老年代,最大值为15。默认是15。