JVM垃圾处理机制

Posted Kirl z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM垃圾处理机制相关的知识,希望对你有一定的参考价值。

JVM垃圾处理机制(一)

1. JVM 简介

JVM: 被裁剪过的虚拟机, 执行字节码指令集的软件

java代码, java进程, jvm之间的关系

1.1 类加载

如果一个类没有发生类加载, 要先执行类加载
加载的时机:

  1. new对象
  2. 读, 写静态变量
  3. 调用静态方法
  4. 父类的类加载: 子类要初始化类加载, 如果父类还没有类加载, 则先执行父类的类加载
  5. 主函数的类: java 类名启动入口类

加载做的事情:

  1. 把字节码 (二进制数据) 加载到 java 进程的方法区 (类型的信息, 方法信息等等)
  2. 在堆中, 生成一个 Class 类对象, 作为方法区类信息 (代码数据) 访问的入口

加载字节码的来源: 不限于class文件, 还可以从其他的地方获取

1.2 关于 JVM

  1. JVM 是定制过的裁剪了部分功能的虚拟机, 模拟硬件执行字节码指令(将字节码翻译为机器码)
  2. java 进程启动时, 就会创建一个 java 虚拟机, 解释执行字节码指令, 还存在 JIT 即时编译器(运行期,
    把热点代码编译为机器码, 之后就不用每次执行都要翻译, 提高效率), 最终是申请系统调度 CPU 执行机器码
  3. 不同虚拟机实现, 可以运行符合字节码规范的代码

基于自己独有的编译器, 编译为符合规范的字节码文件, 使用符合 java 虚拟机规范, 自己定制的 java 虚拟机来运行 (解释, 翻译为机器码)

2. 运行时数据区域

  • 线程私有区域:程序计数器、Java虚拟机栈、本地方法栈
  • 线程共享区域:Java堆、方法区、运行时常量池

线程共享区域, 都是 java 进程启动就会创建

2.1 内存溢出 (OOM)

创建变量/对象/类加载, 需要先在对应的内存区域, 分配一块内存空间, 如果该区域内存不足, 需要执行 gc (垃圾回收), 如果 gc 以后, 内存还是不够, 就会出现内存溢出

结果: 严重的情况, 整个 java 进程挂掉了

解决方案:

  1. 优化代码 (空间复杂度): 复用变量等
  2. java进程启动时, 加大对应内存区域的空间
  3. 如果系统内存不足以满足第2个条件, 还可以加大系统内存

2.2 程序计数器 (线程私有)

程序计数器是一块比较小的内存空间, 可以看做是当前线程所执行的字节码的行号指示器

目的:线程切换出去后, 要恢复时, 下个指令从哪个地方开始执行

不会内存溢出(OOM)

2.3 java 虚拟机栈 (线程私有)

虚拟机栈描述的是Java方法执行的内存模型 : 每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应一个栈帧在虚拟机栈中入栈和出栈的过程。

局部变量表: 存放了编译器可知的各种基本数据类型(8大基本数据类型)、对象引用。

java 虚拟机栈的生命周期与线程相同: 线程启动, 虚拟机栈就创建, 线程销毁, 虚拟机栈也销毁 (出栈自动销毁栈帧, 不需要gc)

栈帧: 一个线程在执行一个方法的时候, 进入方法(创建栈帧, 入栈), 方法返回 (出栈) 生命周期: 和线程执行某个方法的时间相同

可能出现的异常:

  1. StackOverFlowError 异常 : 线程调用的方法链太深 (线程请求的栈深度/栈帧数量 远大于虚拟机允许的深度)
  2. OOM

2.4 本地方法栈 (线程共享)

本地方法栈与虚拟机栈的作用完全一样,他俩的区别无非是本地方法栈为虚拟机使用的Native方法服务,而虚拟机栈为JVM执行的Java方法服务。

2.5 java 堆 (线程共享)

Java堆(Java Heap)是JVM所管理的最大内存区域。Java堆是所有线程共享的一块区域,在JVM启动时创建。此内存区域存放的都是对象实例。JVM规范中说到:“所有的对象实例以及数组都要在堆上分配”。

启动时, 分配堆的内存为最小值, 创建对象空间不足, 就扩展, 如果扩展到最大值且gc后还不够, 就OOM

2.6 方法区 (线程共享)

方法区用于存储已被虚拟机加载的类信息, 常量, 静态变量, 即时编译器编译后的代码等数据

存在gc: 回收常量和类型
类型卸载的条件是非常苛刻的, 所以方法区的gc频率/效率是比较低

没有方法回收区, 就会经常出现 OOM

2.7 运行时常量池 (方法区的一部分)

运行时常量池是方法区的一部分,存放字面量与符号引用。

字面量 : 字符串(JDK1.7后移动到堆中) 、final常量、基本数据类型的值。
符号引用 : 类和结构的完全限定名、字段的名称和描述符、方法的名称和描述符。

以上是关于JVM垃圾处理机制的主要内容,如果未能解决你的问题,请参考以下文章

JVM垃圾处理机制

JVM垃圾处理机制

JVM垃圾处理机制

JVM垃圾处理机制

Java千百问_07JVM架构(008)_java垃圾回收机制是什么

JVM垃圾收集机制