JVM 面试 详解

编程入门 行业动态 更新时间:2024-10-07 08:30:06

JVM 面试 <a href=https://www.elefans.com/category/jswz/34/1770044.html style=详解"/>

JVM 面试 详解

1.ClassLoader相关

1. 什么是类加载器?
读取 Java 字节代码,并转换成java.lang.Class类的一个实例。

2. 类相同的判断?
被相同的类加载加载的类才是相同的类,这里指的“相同”,包括类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法、instanceof关键字等判断出来的结果。

3. 类加载器种类?

  • Bootstrap ClassLoader,加载$JAVA_HOME/jre/rt.jar
  • Extension ClassLoader,加载JAVA_HOME/jre/ext/*.jar
  • Application ClassLoader,加载ClassPath的jar

实例代码

public static void main(String[] args) {// BootStrapClassLoader: Object是rt.jar中的,这个是c实现的,所以是nullSystem.err.println(Object.class.getClassLoader());// AppClassLoader: sun.misc.Launcher$AppClassLoader@73d16e93System.err.println(MyObject.class.getClassLoader());// ExtClassLoader :sun.misc.Launcher$ExtClassLoader@15db9742System.err.println(MyObject.class.getClassLoader().getParent());// ExtClassLoader的父亲是BootStrapClassLoader 打印为nullSystem.err.println(MyObject.class.getClassLoader().getParent().getParent());}

4. 双亲委派模型?
类加载时,首先优先父类加载,父类加载不了就交给子类,子类加载不了就抛出NotFondClassException。

双亲委派模型优点:
由于bootstrapclassloader已经加载了java.lang.String了,所以直接就按照了jdk中的java.lang.String来了,里面是没有main函数的,避免了java的核心API被篡改,还避免了类重复加载。

5. 能否在java程序运行时,动态对类的字节码进行修改?(比如加个方法耗时时间,参数统计)
java探针技术,详情见我们另一篇博客:java探针技术实操 之 java运行时修改类

6.自定义类加载器怎么实现包隔离?
见我另一篇博客实操:自定义类加载器实现不同版本jar共存

2.jvm运行时内存相关

1.java8 JVM运行时内存区域图
程序计数器 : 线程私有,维护线程执行情况(比如:线程切换回来时知道从哪开始执行)。

本地方法栈: 线程私有,服务于native方法。

虚拟机栈: 当线程执行一个方法时,会创建一个对应的栈帧,并将其压栈,当方法执行完毕之后,便会将栈帧出栈。线程结束就回收栈空间。里面存储下面四个东西:
1)、局部变量表
八种基本类型(int,long等)的值,对象的变量名(引用变量)
2)、操作数栈
存储程序中的所有计算过程
3)、指向运行时常量池的引用
4)、方法返回地址

本地内存: 也就是你机器的内存。

方法区(元空间): 线程共享,存储类的元信息,常量、静态变量,java7是存储在堆里面的,java8将其移出来到本地内存里面了。

直接内存: NIO的Buffer提供了一个可以不经过JVM内存直接访问系统物理内存的类——DirectBuffer

: new出来的对象存储区域,详解见下。

3.堆详解


当对象new出来,先放到Eden区(伊甸园区)。第一次垃圾回收时,将存活的对象复制到from区,Eden区清空。当from区也满了,将存活的对象复制到to区,并清空from区,对象年龄加1,并且from和to交换角色,也就是每次垃圾回收时,to区必须是空的,当对象的年龄达到一个阈值(默认值为15)还存活,就移动到老年代。

堆相关参数:
-Xms4g : 初始的Heap的大小(新生代和老年代)。
-Xmx4g:最大Heap的大小。必须设置 -Xms 和 -Xmx的值为一样,因为当Heap不够用时,会发生内存抖动,影响程序运行稳定性。
-Xss512k :设置每个线程的堆栈大小,理论上越大,系统能开的线程越多,但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor(from和to)区)与年老代的比值
-XX:SurvivorRatio=8:设置年轻代中Eden区与Survivor区(from和to)的大小比值。
-XX:MaxTenuringThreshold=15:设置垃圾最大年龄。
-Xmn : 新生代大小。

区域概括
① 新生代(Young Generation):大多数对象在新生代中被创建,其中很多对象的生命周期很短。每次新生代的垃圾回收(又称Minor GC)后只有少量对象存活,所以选用复制算法,只需要少量的复制成本就可以完成回收。

新生代内又分三个区:一个Eden区,两个Survivor区(一般而言),大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到两个Survivor区(中的一个)。当这个Survivor区满时,此区的存活且不满足“晋升”条件的对象将被复制到另外一个Survivor区。对象每经历一次Minor GC,年龄加1,达到“晋升年龄阈值”后,被放到老年代,这个过程也称为“晋升”。显然,“晋升年龄阈值”的大小直接影响着对象在新生代中的停留时间,在Serial和ParNew GC两种回收器中,“晋升年龄阈值”通过参数MaxTenuringThreshold设定,默认值为15。

② 老年代(Old Generation):在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代,该区域中对象存活率高。老年代的垃圾回收(又称Major GC)通常使用“标记-清理”或“标记-整理”算法。整堆包括新生代和老年代的垃圾回收称为Full GC(HotSpot VM里,除了CMS之外,其它能收集老年代的GC都会同时收集整个GC堆,包括新生代)。

③ 永久代(Perm Generation):主要存放元数据,例如Class、Method的元信息,与垃圾回收要回收的Java对象关系不大。相对于新生代和年老代来说,该区域的划分对垃圾回收影响比较小。

GC种类
1.Minor GC: 叫YongGC或GC或轻GC, 对新生代区域的GC,非常频繁,回收速度快。
2.Full GC : 全局GC,对整个新生代、老生代、元空间的全局范围的GC;

GC日志
打印gc日志参数,GC日志既可以直接在命令行输出,也可生成到指定的日志文件中

-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/home/logs/gc.log
public class OrderService {static class Phone {byte[] money = new byte[1024];String name = "i am a phone";}public static void main(String[] args) throws InterruptedException {List<Phone> phones = new ArrayList<OrderService.Phone>();while (true) {phones.add(new Phone());Thread.sleep(1);}}
}

设置运行参数:-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:NewRatio=1
堆大小:10M
年轻代与老年代的比例约为 1:1

执行结果:

[GC (Allocation Failure) [PSYoungGen: 4096K->480K(4608K)] 4096K->4008K(9728K), 0.0013970 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 480K->0K(4608K)] [ParOldGen: 3528K->3848K(5120K)] 4008K->3848K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0067804 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->3064K(4608K)] [ParOldGen: 3848K->4807K(5120K)] 7944K->7872K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0088351 secs] [Times: user=0.11 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4038K(4608K)] [ParOldGen: 4807K->4807K(5120K)] 8903K->8846K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0055923 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4095K(4608K)] [ParOldGen: 4807K->4807K(5120K)] 8903K->8903K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0048371 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4825K->4825K(5120K)] 8921K->8921K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0047980 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4842K->4842K(5120K)] 8938K->8938K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0048467 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4859K->4859K(5120K)] 8955K->8955K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0047925 secs] [Times: user=0.11 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4876K->4876K(5120K)] 8972K->8972K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0086871 secs] [Times: user=0.11 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4893K->4893K(5120K)] 8989K->8989K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0047263 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4910K->4910K(5120K)] 9006K->9006K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0048743 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4927K->4927K(5120K)] 9023K->9023K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0047919 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4944K->4944K(5120K)] 9040K->9040K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0047698 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4961K->4961K(5120K)] 9057K->9057K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0047385 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4978K->4978K(5120K)] 9074K->9074K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0050405 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 4995K->4995K(5120K)] 9091K->9091K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0048963 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5012K->5012K(5120K)] 9108K->9108K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0048850 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5029K->5029K(5120K)] 9125K->9125K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0051970 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5046K->5046K(5120K)] 9142K->9142K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0050820 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5063K->5063K(5120K)] 9159K->9159K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0048128 secs] [Times: user=0.09 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5080K->5080K(5120K)] 9176K->9176K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0051470 secs] [Times: user=0.11 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5097K->5097K(5120K)] 9193K->9193K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0047988 secs] [Times: user=0.11 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5114K->5114K(5120K)] 9210K->9210K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0050377 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5119K->5119K(5120K)] 9215K->9215K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0051825 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5119K->5119K(5120K)] 9215K->9215K(9728K), [Metaspace: 2618K->2618K(1056768K)], 0.0049117 secs] [Times: user=0.11 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4096K->0K(4608K)] [ParOldGen: 5119K->502K(5120K)] 9215K->502K(9728K), [Metaspace: 2619K->2619K(1056768K)], 0.0046179 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Exception in thread "main" HeapPSYoungGen      total 4608K, used 108K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)eden space 4096K, 2% used [0x00000000ffb00000,0x00000000ffb1b068,0x00000000fff00000)from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)ParOldGen       total 5120K, used 502K [0x00000000ff600000, 0x00000000ffb00000, 0x00000000ffb00000)object space 5120K, 9% used [0x00000000ff600000,0x00000000ff67dba0,0x00000000ffb00000)Metaspace       used 2651K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 283K, capacity 386K, committed 512K, reserved 1048576K
java.lang.OutOfMemoryError: Java heap spaceat jvm.OrderService$Phone.<init>(OrderService.java:9)at jvm.OrderService.main(OrderService.java:17)

解释:
1.YongGC

[GC (Allocation Failure) [PSYoungGen: 4096K->480K(4608K)] 4096K->4008K(9728K), 0.0013970 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
  1. GC : 表示是一次YGC(Young GC)。
  2. Allocation Failure : 表示失败的类型。年轻代中没有足够区域能够存放需要分配的数据而失败
  3. PSYoungGen : 表示年轻代情况。
  4. 4096K->480K : 回收前年轻代占用4096K,回收后占用480K(都移到老年代了)。
  5. 4608K : 年轻代大小(上面设置了比例为1:1,整堆大小约10M, 一半刚好差不多是4608)。
  6. 4096K->4008K : 整个堆占用从4096K降为4008K,压根没怎么回收。
  7. 9728K :整个堆的大小。
  8. 0.0013970 secs : GC用的总时间。
  9. [Times: user=0.00 sys=0.00, real=0.00 secs] : 分别表示,用户态占用时长,内核用时,真实用时。

2.FullGC

[Full GC (Ergonomics) [PSYoungGen: 4096K->0K(4608K)] [ParOldGen: 5119K->502K(5120K)] 9215K->502K(9728K), [Metaspace: 2619K->2619K(1056768K)], 0.0046179 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
  1. Full GC : 表示是一次Full GC。
  2. [PSYoungGen: 4096K->0K(4608K)] :年轻代:垃圾收集前->垃圾收集后(年轻代堆总大小)
  3. [ParOldGen: 5119K->502K(5120K)] : 老年代:垃圾收集前->垃圾收集后(年老代堆总大小)
  4. 9215K->502K(9728K) : 垃圾收集前->垃圾收集后(总堆大小)
  5. [Metaspace: 2619K->2619K(1056768K)] : Metaspace空间信息,垃圾收集前->垃圾收集后(总元空间大小)

3.面试题

1.老年代和新生代的比例
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。

2.YGC和FGC发生的具体场景
YGC: 新生代(eden区)不足,执行 young gc
FGC: old空间不足,perm空间不足,调用方法System.gc() ,ygc时的悲观策略, dump live的内存信息时(jmap –dump:live),都会执行full gc。

3.GC回收算法?
标记-清除法: 标记出没有用的对象,然后一个一个回收掉。
缺点:标记和清除两个过程效率不高,产生内存碎片导致需要分配较大对象时无法找到足够的连续内存而需要触发一次GC操作。

复制算法: 按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。
缺点:将内存缩小为了原来的一半。

标记-整理法:标记出没有用的对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内。
优点:解决了标记- 清除算法导致的内存碎片问题和在存活率较高时复制算法效率低的问题。

分代回收: 根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

更多推荐

JVM 面试 详解

本文发布于:2024-02-28 11:46:51,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1769246.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:详解   JVM

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!