JVM内存模型
内存模型介绍一下
- 程序计数器:线程私有的且不会内存溢出,作用就是记住下一条jvm的地址
- 虚拟机栈:线程私有的,每个线程运行时需要的内存就是虚拟机栈,它包括栈帧(每个方法就是一个栈帧),栈帧存放局部变量表、操作数栈、动态链接、方法返回地址
- 本地方法栈;私有的实现本地方法调用
- 方法区或元空间:线程共享,存储类元数据(类结构、方法元数据、常量池)
- 堆内存:线程共享,对象实例和数组在这里分配以及可通过GC回收
- 直接内存:通过本地方法直接向操作系统申请内存,不属于堆而是属于本地内存
JVM内存模型里的堆和栈有什么区别?
- 堆是线程共享的,栈是线程私有的
- 栈存放的是局部变量以及参数和返回地址,但是堆存放的是对象实例
- 堆的内存空间比栈大
- GC不会对栈生效
栈中存的到底是指针还是对象?
MyObject obj = new MyObject();
这里的obj
实际上是一个存储在栈上的引用,指向堆中实际的对象实例
堆分为哪几部分呢?
- 新生代
- 伊甸园
- 幸存区(from to)
- 老年代
方法区中的方法的执行过程方法区中的方法的执行过程?
- 解析方法调用
- 创建栈帧
- 执行方法
- 返回方法结果
引用类型有哪些?有什么区别?
- 强引用:不会被GC
- 软引用:第一次GC后,内存不足才GC
- 弱引用:直接GC
- 虚引用:配合引用队列,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用虚引用相关方法unsafe.freememory()释放直接内存
弱引用了解吗?举例说明在哪里可以用?
-
使用弱引用持有监听器, 当监听器对象不再被强引用时,GC自动回收
-
在框架中管理类加载器的元数据
// 弱引用关联动态生成的类及其类加载器 WeakReference<Class<?>> dynamicClassRef = new WeakReference<>(generatedClass); // 当类加载器被回收时,动态类也会被GC回收,避免PermGen/Metaspace泄漏
内存泄漏和内存溢出的理解?
- 内存泄漏:不在使用的对象任然被引用,无法GC
- 静态集合未清理
- 线程持有对象
- 内存溢出:内存泄漏导致内存不足
- 大量对象创建
- 递归调用
jvm 内存结构有哪几种内存溢出的情况?
- 堆内存溢出:大对象没有合适的内存存储
- 栈内存溢出:栈帧过大或者栈帧过多
- 直接内存溢出
- 元空间溢出:第三方包很多以及动态生成类很多