JVM的一些常见面试题:
说说类加载过程
加载->链接(验证,准备,解析)->初始化
加载阶段::查找并加载类的二进制数据
验证:确保加载的类的正确性
准备:为类的静态变量分配内存,并将其初始化为默认值
解析:把类中的符号引用转换为直接引用
初始化:对类的静态变量,静态代码块执行初始化操作
类加载器有几种?如何破坏双亲委派机制?
系统默认有三种。引导类加载器,拓展类加载器,系统类加载器;不过还可以自定义类加载器。
自定义类加载器(继承ClassLoader),重写loadClass方法。
如何自定义类加载器?
创建一个类,继承ClassLoader类,重写findClass方法,findClass方法内调用defineClass方法。
jdk1.8默认的垃圾收集器是什么?
- 1.7和1.8使用parellelGC和parellelOldGC,1.9之后一直是g1
如果查看当前使用的是什么垃圾收集器?(如何查看jvm参数?)
- 通过命令java -XX:+PrintCommandLineFlags -version可以打印jvm的各种参数,里面就有使用的垃圾收集器。
cpu一直占用过高,如何排查?
- 首先使用top命令来找到cpu占用高的进程(window使用jps),如果是java进程,记住pid。
- 然后再使用top -Hp pid来找出该进程中占用cpu最多的线程。
- 将堆栈信息保存到一个.log文件,使用命令 jstack pid > thread_stack.log
- 最后打开该文件,将线程的pid转换成16进制,然后在该文件里面找到该线程的信息就可以了。
高内存占用,如何排除?
- 首先使用top命令来找到内存占用高的进程(window使用jps),如果是java进程,记住pid。
- 使用ps p pid -L -o pcpu,pmem,pid,tid,time,tname,cmd 找到进程中内存占用高的线程pid
- 将堆栈信息保存到一个.log文件,使用命令 jstack pid > thread_stack.log
- 最后打开该文件,将线程的pid转换成16进制,然后在该文件里面找到该线程的信息就可以了。
什么时候会触发GC?
当Eden满了的时候,会触发minorGC
当老年代空间不足的时候,会触发fullGC
当方法区空间不足的时候,也会触发fullGC
当minorGC进入老年代的数据大小大于老年代剩余空间大小的时候,会触发fullGC
调用System.gc()建议执行垃圾回收的时候会调用fullGC
GC如何判断一个对象是否可回收?
引用计数法:每个对象都有一个引用计数器,用来统计指向对象的引用。有新引用指向对象,引用计数器加一,一个引用不再指向对象,引用计数器减一,如果引用计数器为零,对象会可回收。(不过java中没有采用该方法,因为无法处理循环引用)
可达性分析法:从GC Roots开始往下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,证明该对象不可用,虚拟机就判断该对象可回收。不过可回收不代表一定会被回收,有可能在即将回收对象,执行finalize方法的时候重新有引用指向该对象,那么该对象就会复活,不过只可以复活一次。
哪些对象可作为GC Roots?
虚拟机栈引用的对象。
方法区中静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中引用的对象。
未完待续…