- JVM体系结构
- java的内存模型
程序计数器
java虚拟机栈
本地方法栈
方法区
堆
- Java内存模型中什么数据放在什么区域
JDK 1.6
方法区 保存了类信息,静态变量,常量,常量池信息
堆 保存所有对象实例数据
JDK 1.8 堆保存常量池
- 类加载过程
1 加载 查找对应路径的class文件导入
2 检查 检查加载的class文件的正确性
3 准备 给类中的静态变量分配内存空间
4 解析 将常量池中的符号引用替换成直接引用
5 初始化 对静态变量和静态代码执行初始化工作
- 类加载器有几种?
4 种,启动类加载器,扩展类加载器,应用程序类加载器,自定义加载器
- 双亲委派机制及使用原因
当一个类加载器收到了类加载的请求,它会先交给上面的父类加载器检查是否加载过,然后从上往下尝试加载类。
避免多份同样字节码的加载
- 怎么打破双亲委派模式
1 在构造类加载器时将parent设为null
2 继承ClassLoader重写loadclass方法,改变类的查找机制
- 什么是java内存泄漏,会导致什么问题??举几个例子。怎么防止内存泄漏
1 内存泄露是指已经被分配的堆内存由于某种原因无法释放,造成内存的浪费
2 数据库连接对象或者IO对象使用没有关闭
循环引用
某个程序的运行时间中一个对象很早就不再引用却被没有被释放
3 及时释放对象
使用软引用和弱引用
使用完对象后把它设置成null,这样会撤销强引用,提升回收时间
集合对象用完后进行clear
不要频繁使用String对象,因为会造成碎片化。
- 堆栈什么时候会爆出
递归超过一定深度
- 内存溢出和内存泄露的区别
内存溢出是指申请内存时,没有足够的内存空间可以使用
内存泄露指已经分配的堆内存由于某种原因无法释放,最后会造成内存溢出
- 什么情况会爆出OOM
1 最常见的是堆空间不足
2 创建不了新线程 因为创建的线程过多占用了内存
3 类加载时,方法区空间不足
- oom异常如何解决
1 先做代码方面的优化 及时关闭一些连接对象,合理的使用弱引用和软引用
2 调整运行参数,调整可用堆空间的内存。 (xss规定每个线程虚拟机堆栈的大小,xms设置堆的初始值,xmx设置堆的最大值)
- 循环引用会造成内存泄露吗?
会
- 一个进程有三个线程,当一个线程爆出OOM之后,另外两个线程的状态
照样运行,因为一个线程爆出OOM后,会释放掉它所用的内存空间。
- 垃圾回收算法 新生代和年老代用的什么算法,为什么用这个算法?
标记-清除算法
标记-整理算法
复制算法
分代回收算法 对新生代和老年代用不同的垃圾回收算法
新生代一般使用复制算法 因为新生代周期一般比较短
老年代一般使用标记-整理算法 因为老年代比较稳定,移动不是很频繁,减少碎片化。
- 如何判断是否需要回收对象
引用计数算法 给对象添加计数器,引用加1,引用失效就减1,当计数器为0就回收
可达性分析算法 通过判断对象的引用链是否可达来决定对象是否可以被回收
- 引用计数的缺陷
无法检测循环引用的情况,这样会内存泄露
- 什么样的对象可以当作gcroot
虚拟机中栈中引用的对象
方法区中常量和类静态属性引用的对象
本地方法栈中Native方法的引用对象
活跃线程的引用对象
- GC 机制
GC机制,主要就是Minor GC和Full GC。MInor GC是对新生代的垃圾回收,用的是复制算法,
主要就是有一个eden区,两个survivor区,数据先放在eden区,然后生存下来的进入survivor区,默认经过15次minor GC进入老年代。然后老年代空间不足或者调用system.gc()就进行full gc对新生代和老年代进行垃圾回收。
- JVM运行过程
加载class文件(把类信息放在方法区内),管理并分配内存,执行垃圾回收。
- 什么情况下会出现full GC
老年代空间不足,调用System.gc()
还有JDK 1.6之前 永久代空间不足
- 新生代和老年代的默认比例
1:2
- java新生代GC多少次后晋升到老年代
默认15
- JVM的垃圾收集器,
Serial Serial Old
ParallelScanvenge Paraller Old
CMS G1
- G1和CMS有啥区别?
G1 对新生代和老年代都执行,对新生代执行标记,整理方法。对老年代执行标记整理算法。
CMS 是针对老年代的,进行标记清除算法。