深入理解Java虚拟机JVMjvm
jvm包括类加载子系统,字节码执行引擎(执行代码),运行时数据区(内存区域最重要包括(堆(new出来的对象),栈(线程(存放局部变量),所以又叫做线程栈),本地方法栈,程序计数器,方法区(元空间))。
main线程会分配一个栈内存空间,供线程专享。
栈内部结构复杂
{
栈的内部由栈帧组成,每运行一个方法,分配一块内存区,这样的一个方法对应的内存区,叫做栈帧。main方法也分配一个内存区域。这样叫栈帧。与数据结构的栈一样。
不同的方法由自己的局部变量。
栈:先进后出FILO
main方法先执行先分配栈帧内存区,然后按照代码顺序运行下面的方法,执行完出栈。
}
栈帧内部存有局部变量表,操作数栈,动态链接,方法出口
打开class目录,打开字节码文件, 16进制
bin目录下javap - c命令对class文件反编译
jvm指令手册查找
程序计数器
{
也是分配
每个线程专属,存放正在或即将执行的代码的行号(内存地址)
}
操作数栈(操作数运算时的中转区域)
方法出口:存取局部方法结束在后main方法的位置
栈 存对象对应的内存地址
栈上面的局部变量存的是堆上的对象的地址
方法区 存放静态变量,类元信息,常量。
类元信息,类的组成信息,相关代码,类名之类的。
方法区域栈中有无数的对象指针
对象(堆区)
{
对象头
实例数据
标记字段(检查锁)
类型指针 jvm会为每一个对象在对象头里面存取类型指针。
}
对象头在方法区存取了对象的类型
本地方法栈
{
本地方法 native关键字有C语言实现
本地方法调用C语言代码
寻找底层C语言实现 xx.dll(C语言库函数)
存取本地方法中可能需要的局部变量(C代码中的(C语言代码中可能有变量))
}
堆(jvm调优)600m
{
年轻代 200m一直new超过就触发一种垃圾回收机制(满了 minor gc(gc的一种)(专门处理伊甸园区垃圾对象))
{
Eden区 160m
}
minor gc第一次会把垃圾先扫掉,存活下来的分代年龄+1,移入Survivor区满了,然后继续gc ,还存活的分代年龄继续+1(复制算法,方便移动年轻代),分代年龄达到15,经历16=5次gc 移入老年代
Survivor区 40m
老年代也满了后进行full gc,收集空间比minor gc大,在进行垃圾回收时,会停止用户线程,专门开启垃圾回收线程寻找垃圾对象。
老年代 400m,老年代满了话发生OOM
}
java visualvm Java调优工具(需要装可视化插件可以呈现gc time)
GC Root根:枚举根节点线程栈的本地变量,变量还存活,指向对象。
gc日志
有个一行参数加入程序中,存取程序进行gc的日志(里面包含gc的原因)
方法区也会full gc 原因:类太多啦
方法区也可以动态扩容,但可以自己分配内存空间,减少时间。