JVM
运行时数据区
线程共享
所有线程能访问这块内存数据,随虚拟机或GC创建和销毁
线程独占
每个线程都会有它独立的空间,随线程生命周期而创建和销毁
方法区
作用:存储加载的类信息、常量、静态变量、JIT编译后的代码等数据
GC:
- 方法区存在垃圾回收,但是回收频率很低;
- 回收主要针对常量池的回收,和类型的卸载;
- 当方法区无法满足内存时,报OOM(out of memory)。
堆内存
作用:唯一的目的就是存放对象实例,几乎所有的对象、数组都在这里存放
对于大多数应用来说,堆是JVM管理的内存中最大的一块内存区域,也是最容易OOM的区域
大多数JVM都将堆实现为大小可扩展的(通过-Xmx、-Xms控制)
引用算法
引用计数器算法:存在两个对象相互引用的问题
可达性分析算法:主力的商用程序语言(Java、C#)都是通过可达性分析算法来判断对象是否存活的,GC Roots可以是:
- 虚拟机栈
- 方法中静态属性引用的对象
- 方法区中常量引用的对象
- Native方法引用的对象
虚拟机栈
线程中方法执行的模型,每个方法执行时,就会在虚拟机栈中创建一个栈帧,每个方法从调用到执行的过程,就对应这栈帧在虚拟机栈中从入栈到出栈的过程。
栈帧:虚拟机栈由多个栈帧(Stack Frame)组成。一个线程会执行一个或多个方法,一个方法对应一个栈帧。
本地方法栈
和虚拟机栈功能类型,虚拟机栈是为虚拟机执行JAVA方法而准备的,本地方法栈是为虚拟机使用Native方法而准备的。
程序计数器
程序计数器(Program Counter Register)记录当前线程执行字节码的位置,字节码解析器工作时,就是通过改变计数器的值来选取下一条需要执行的字节码指令。
如果执行java方法,存储的是字节码指令地址,如果执行Native方法,则计数器值为空
程序计数器是唯一一个没有任何OOM的区域
直接内存
直接内存是不属于JVM内存区域,是我们常说的堆外内存。
Java引用NIO之后,可以使用Native函数库直接分配对外内存,然后通过一个存在Java堆中的DirectByteBuffer对象作为操作这块内存区域的引用进行操作。
直接内存不受java对大小的限制,当内存总和大于机器物理内存时,才会OOM。
Class文件
class文件包含JAVA程序执行的字节码;数据严格按照格式紧凑排列在class文件中的二进制流,中间无任何分隔符; u1、 u2、 u4、 u8都是无符号数,表示前面的多少个字节码(例如u2表示class文件中的2个字节码); info结尾都是表 。
全限定名
把类全名中的. 替换成/,例如org/fenixsoft/clazz/TestClass;
简单名称
是指没有类型和参数修饰的方法或者字段名称,如 public int inc(){} , 简单名称就是inc, public int age 字段,简单名称就是age
描述符
比较复杂,描述符的偶用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值。如“int[]” 将被标记为“[I”
java.lang.String[][] ,被标记为“[[Ljava/lang/String;”;
java.lang.String toString() 的描述符为()Ljava/lang/String