JVM内存结构
类加载器
@Test
public void test(){
//类加载器包在rt包下
ClassLoaderDemo classLoaderDemo = new ClassLoaderDemo();
//sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(classLoaderDemo.getClass().getClassLoader());
//sun.misc.Launcher$ExtClassLoader@1f32e575
System.out.println(classLoaderDemo.getClass().getClassLoader().getParent());
//null,根加载器存在,但是拿不到
System.out.println(classLoaderDemo.getClass().getClassLoader().getParent().getParent());
}
双亲委派机制:
类加载器寻找类已经有的:App->Ext->Boot
避免类重名被覆盖,保证Java类库的安全,类加载器收到类加载请求,Boot有就用,没有就向下找—>Ext有就用,没有就向下找—>App没有就向下抛ClassNotFound,最后抛给App
沙箱安全机制
不同的代码在不同权限的域里执行
沙箱的组件
字节码校验器:确保Java类文件遵循Java语言规范,但并不是所有类文件都会经过字节码校验,如核心类
类装载器:防止恶意代码干涉正常代码
守护被信任的类库边界
将代码归入保护域,确定了代码可以执行哪些操作
虚拟机为不同的类加载器提供不同的命名空间,命名空间由一系列唯一的名称组成每一个被装在的类都有一个名字,这个命名空间是由Java虚拟机为每一个类装载器维护的,他们互相之间不可见
类装载器采用的是双亲委派机制:
1.从最内层JVM自带类加载器开始加载,外层恶意同名类得不到加载
2.由于严格通过包来区分了访问域,外层恶意类通过内置代码也无法活得权限访问到内层类,所以保护了内部代码不被恶意破坏
Native
本地方法栈调用C语言库
PC寄存器
每个线程都有一个私有的程序计数器,指针,指向方法区中的字节码中的下一条代码指令, 非常小,可以忽略不计
方法区
被所有线程共享的,所有字段和方法的字节码,以及一些特殊的方法,如构造器,接口代码也在此定义,即所定义的方法信息都保存在此,该区域属于共享空间
静态变量、常量、类信息(构造方法,接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关
static final Class 常量池
栈
先进后出,后出先进。main()最先执行,最后结束
栈内存主管程序的运行,生命周期和线程同步。
基本类型数据+对象引用+实例的方法
运行原理,栈帧
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O955VAyR-1652793983212)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20220408102107822.png)]
堆
Heap
/**配置入口help–>edit custom vm options
* help–>edit custom vm options
* -Xms2048m #设置JVM初始堆内存为2048m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
* -Xmx8192m #设置JVM最大堆内存为8192m。
* -XX:ReservedCodeCacheSize=1000m #代码缓存
* -XX:+UseConcMarkSweepGC #设置年老代为并发收集
* -XX:SoftRefLRUPolicyMSPerMB=50 #“软引用”的对象在最后一次被访问后能存活50毫秒
* -ea #打开断言功能
* -XX:CICompilerCount=2 #编译线程的数目
* -Dsun.io.useCanonPrefixCache=false
* -Djava.net.preferIPv4Stack=true #java网络编程只支持ipv4
* -Djdk.http.auth.tunneling.disabledSchemes=""
* -XX:+HeapDumpOnOutOfMemoryError #表示当JVM发生OOM时,自动生成DUMP文件
* -XX:-OmitStackTraceInFastThrow #省略异常栈信息从而快速抛出
* -Djdk.attach.allowAttachSelf #保存配置
* -Dkotlinx.coroutines.debug=off #Kotlin协程调试
* -Djdk.module.illegalAccess.silent=true
* -javaagent:E:\idea\jetbrains-agent-latest\jetbrains-agent\jetbrains-agent.jar #指定Java代理包
* -XX:MaxMetaspaceSize=8192m #元空间大小设置
* jvm内存调节Run->Edit Configurations->Build and Run 命令行:-ea -XX:+PrintGCDetails在ALT+V。鼠标放上去有提示
*/
@Test
public void test1(){
/**
* jvm最大内存 jvmMax=1875378176Byte = 1788M
* 默认情况下是PC内存的1/4
*/
long jvmMax = Runtime.getRuntime().maxMemory();
/**
* jvm初始化内存 jvmTotal=126877696Byte = 121M
* 默认情况下是PC内存的1/64
*/
long jvmTotal = Runtime.getRuntime().totalMemory();
System.out.println("jvmMax="+jvmMax+"Byte = "+jvmMax/1024/1024+"M");
System.out.println("jvmTotal="+jvmTotal+"Byte = "+jvmTotal/1024/1024+"M");
}
/**
*PSYoungGen+ParOldGen≈jvmTotal,说明Metaspace逻辑上存在,物理上不存在
*/
jvmMax=1875378176Byte = 1788M
jvmTotal=126877696Byte = 121M
Heap
PSYoungGen total 37888K, used 7872K [0x00000000d6180000, 0x00000000d8b80000, 0x0000000100000000)
eden space 32768K, 24% used [0x00000000d6180000,0x00000000d69300a8,0x00000000d8180000)
from space 5120K, 0% used [0x00000000d8680000,0x00000000d8680000,0x00000000d8b80000)
to space 5120K, 0% used [0x00000000d8180000,0x00000000d8180000,0x00000000d8680000)
ParOldGen total 86016K, used 0K [0x0000000082400000, 0x0000000087800000, 0x00000000d6180000)
object space 86016K, 0% used [0x0000000082400000,0x0000000082400000,0x0000000087800000)
Metaspace used 5147K, capacity 5272K, committed 5504K, reserved 1056768K
class space used 598K, capacity 627K, committed 640K, reserved 1048576K
OOM排错
内存快照分析工具,MAT, Jprofiler:安装客户端后需要在idea中指定执行文件位置,Tools->jprofiler->jprofiler executable
分析Dump文件。需要配置jvm HeapDumpOnOutOfMemoryError。报错后生成到代码目录,打开后找大对象。ThreadDump可以定位到线程中的代码位置
GC
两种:轻量级GC 全局GC(Full GC)
JVM在进行GC时,大部分是在新生代回收
GC算法
内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)
内存整齐度:复制算法=标记压缩算法>标记清除算法
内存利用率:标记压缩算法>标记清除算法>复制算法
GC分代收集算法:
新生代:存活率低,复制算法
老年代:区域大,存活率高,标记清除+标记压缩混合算法(N次清除{控制好内存碎片两}后在压缩)
JMM
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h2iWKhzP-1652793983218)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20220408123617388.png)]
算法
内存利用率:标记压缩算法>标记清除算法>复制算法
GC分代收集算法:
新生代:存活率低,复制算法
老年代:区域大,存活率高,标记清除+标记压缩混合算法(N次清除{控制好内存碎片两}后在压缩)
JMM
[外链图片转存中…(img-h2iWKhzP-1652793983218)]