1. JVM如何加载一个类过程
类加载过程:
- 加载
- 验证
- 验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成伤害
- 准备
- 准备阶段为变量分配内存并设置类变量的初始化
- 解析
- 解析过程是将常量池内的符号引用转换为直接引用
- 初始化
2. 双亲委派模型的概念与方法
双亲委派是指:如果一个类收到类加载的请求,不会自己先尝试加载,先找父类加载器去完成。当顶层启动类加载器表示无法加载这个类的时候,子类才会尝试自己去加载。当回到最开始的发起者加载器时,发起者加载器也无法加载就会抛出ClassNotFound
异常。使用双亲委派模型的目的是:防止内存中出现多份同样的字节码
双亲委派模型中的方法:
- 启动类加载器
- 标准扩展类加载器
- 应用程序类加载器
- 上下文类加载器
3. GC算法(什么样的对象算是可回收对象,可达性分析),CMS收集器
JVM是如何判断一个对象已经变成了可回收的“垃圾”,一般是两个方法:
- 引用记数法
- 引用计数法没办法解决循环引用的问题
- 根搜索算法
- 从一系列的“GC Roots”对象开始向下搜索,搜索走过的路径称为引用链。当一个对象到“GC Roots”之间没有引用链时,被称为引用不可达。引用不可达的对象认为是不回收的对象。
几种垃圾收集器:
- Serial New / Serial old
- Parrallel New
- Parrallel Old
- CMS(采用的是Mark - Sweep算法)
- G1(是一种并行与并发收集器,并且可建立可以预测的停顿时间模型,整体上是基于标记清理,局部采用复制)
4. JVM新生代,老年代,持久带,都存储什么内容?
- 持久带:主要存放的是Java类的类信息,与垃圾收集器要收集的Java对象关系不大;
- 新生代:所有新生成的对象首先都是放在新生代;
- 老年代:存放的都是一些生命周期较长的对象。
5. 内存溢出和内存泄漏:
- 内存溢出:程序申请内存时,没有足够的内存,
OutOfMemory
- 内存泄漏:内存泄漏时,垃圾对象无法回收,可以使用memory analyzer工具查看泄漏
6. 进程与线程
- 进程:进程指运行中的程序(独立性、动态性、并发性)
- 线程:进程中的顺序执行流
- 进程与线程的区别:
- 进程间不共享内存
- 创建进程进行资源分配的代价要大得多,所以多线程在高并发环境中效率高
7. 序列化与反序列化
序列化指将Java对象转化为字节序列,反序列化相反。主要时为了Java线程间通讯,实现对象传递。只有实现了Serializable或Externalizable接口对象才可被序列化。
8. 64位JVM中,int长度是多少
Java中,int类型变量的长度是一个固定值,与平台无关,都是32位。即,在32位和64位的Java虚拟机中,int类型的长度是相同的。
9. 解释Java堆空间及GC
当通过Java命令启动Java进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从堆空间进行分配内存。
GC是JVM内部的一个进程,回收无效对象的内存用于将来的分配
10. Java中堆和栈有什么区别?
JVM中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。
栈通常都比堆小,也不会再多个线程之间共享,而堆被整个JVM的所有线程共享。
11. Java中垃圾回收有什么目的?什么时候进行垃圾回收?
垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源。
12. System.gc()
与Runtime.gc()
会做什么事情?
这两个方法用来提示JVM要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决于JVM的
13. finalize()
方法什么时候被调用?析构函数finalization
的目的是什么?
在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()
方法,一般建议在该方法中释放对象持有的资源
14. 如果对象的引用被置为null,垃圾收集器是否会立即释放后对象占用的内存?
不会,在下一个垃圾回收周期中,这个对象将是可被回收的。
15. Java堆的结构是什么样子的?
JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在JVM启动的时候被创建。对象所占的堆内存是由自动内存管理系统即垃圾收集器回收。
16. 串行收集器和吞吐量收集器的区别是什么?
吞吐量收集器使用并行版本的新生代垃圾收集器,它用于中等规模和大规模数据的应用程序。
串行收集器堆大多数的小应用(在现代处理器上需要大约100M内存)就足够了。
17. JVM的永久代中会发生垃圾回收吗?
垃圾回收不会发生在永久代,如果永久代填满了或者超过了临界值,就会触发完全垃圾回收(Full GC)。
如果仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的,这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。