JVM 面试 - JiyangM/spring GitHub Wiki

https://www.cnblogs.com/wmyskxz/p/9045972.html

https://www.jianshu.com/p/54eb60cfa7bd

Java 虚拟机是如何判定两个 Java 类是相同的?

Java 虚拟机是如何判定两个 Java 类是相同的。Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。比如一个 Java 类

 public void testClassIdentity() { 
    String classDataRootPath = "C:\\workspace\\Classloader\\classData"; 
    FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath); 
    FileSystemClassLoader fscl2 = new FileSystemClassLoader(classDataRootPath); 
    String className = "com.example.Sample"; 	
    try { 
        Class<?> class1 = fscl1.loadClass(className); 
        Object obj1 = class1.newInstance(); 
        Class<?> class2 = fscl2.loadClass(className); 
        Object obj2 = class2.newInstance(); 
        Method setSampleMethod = class1.getMethod("setSample", java.lang.Object.class); 
        setSampleMethod.invoke(obj1, obj2); 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
 }

对象分配规则?

JVM指令重排序?

在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件:

  1. 在单线程环境下不能改变程序运行的结果;
  2. 存在数据依赖关系的不允许重排序

重排序会产生问题,比如一个boolean类型的变量初始值是false,然后后面是一段业务逻辑,执行完后将boolean的值置为true,当指令重排序的时候可能会将业务顺序和变量赋值的顺序调整,这样的话就会有问题。

volatile 保证了原子可见性和顺序性,实现参见:

https://github.com/JiyangM/spring/wiki/volatile

内存屏障?

答:内存屏障,又称内存栅栏,是一组处理器指令,用于实现对内存操作的顺序限制。

类加载器是如何加载 class 文件的?

类似-Xms、-Xmn这些参数的含义:

堆内存分配:

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64

JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4

默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。

因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。 非堆内存分配:

JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;

由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。 -Xmn2G:设置年轻代大小为2G。

-XX:SurvivorRatio,设置年轻代中Eden区与Survivor区的比值。

内存泄漏和内存溢出

概念:

  • 内存溢出指的是内存不够用了。
  • 内存泄漏是指对象可达,但是没用了。即本该被GC回收的对象并没有被回收
  • 内存泄露是导致内存溢出的原因之一;内存泄露积累起来将导致内存溢出。
  • 内存泄漏的原因分析:

内存泄漏的原因分析:

  • 长生命周期的对象引用短生命周期的对象
  • 没有将无用对象置为null

简述一下 Java 中创建一个对象的过程?

对象的内存布局是怎样的?

对象是如何定位访问的?

GC什么时候开始?

引用的分类?

垃圾收集器?

对象是如何定位访问的?

对象的访问定位有两种:句柄定位和直接指针。

这两种对象的访问方式各有优势,使用句柄访问方式的最大好处就是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要被修改。

使用直接指针访问方式的最大好处就是速度更快,它节省了一次指针定位的的时间开销。