类加载的生命周期?
加载、验证、准备、解析、初始化五个阶段
类加载器的层次?
启动类加载器: Bootstrap ClassLoader
扩展类加载器: Extension ClassLoader
应用程序类加载器: Application ClassLoader
自定义类加载器: 因为JVM自带的ClassLoader
Class.forName()和ClassLoader.loadClass()区别?
- Class.forName(): 将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块;
- ClassLoader.loadClass(): 只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。
- Class.forName(name, initialize, loader)带参函数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象
JVM类加载机制有哪些?
- 全盘负责
- 父类委托
- 缓存机制
- 双亲委派机制
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
这样好处,是避免应用层改写String同名类,而导致jdk自身的类被替换掉,有了双亲委派,则可以避免这个问题,所有类都由最顶级的启动器类加载器来加载;
内存结构
线程私有:程序计数器、虚拟机栈、本地方法栈
线程共享:堆、方法区, 堆外内存(Java7的永久代或JDK8的元空间、代码缓存)
栈帧的内部结构?
- 局部变量表(Local Variables)
- 操作数栈(Operand Stack)(或称为表达式栈)
- 动态链接(Dynamic Linking):指向运行时常量池的方法引用
- 方法返回地址(Return Address):方法正常退出或异常退出的地址
堆区内存是怎么细分的?
年轻代 (Young Generation) Minor GC
伊甸园 Eden Memory 默认比例是8:1:1
两个幸存区 from/to或s0/s1
老年代(Old Generation) Major GC
对象有哪些引用类型?
- 强引用 被强引用关联的对象不会被回收。
- 软引用 被软引用关联的对象只有在内存不够的情况下才会被回收。
- 弱引用 被弱引用关联的对象一定会被回收,也就是说它只能存活到下一次垃圾回收发生之前。
- 虚引用 又称为幽灵引用或者幻影引用。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用取得一个对象。
有哪些基本的垃圾回收算法?
标记 - 清除
标记 - 整理
复制
分代收集
如何判断一个对象是否可以回收?
引用计数算法
可达性分析算法
垃圾回收种类
- 新生代收集(Minor GC/Young GC):只是新生代的垃圾收集
- 老年代收集(Major GC/Old GC):只是老年代的垃圾收集
- 目前,只有 CMS GC 会有单独收集老年代的行为
- 很多时候 Major GC 会和 Full GC 混合使用,需要具体分辨是老年代回收还是整堆回收
- 混合收集(Mixed GC):收集整个新生代以及部分老年代的垃圾收集
- 目前只有 G1 GC 会有这种行为
- 整堆收集(Full GC):收集整个 Java 堆和方法区的垃圾 调用 System.gc(),老年代空间不足