Administrator
发布于 2026-05-17 / 2 阅读
0

JVM进阶

# 类加载器 - App类加载器 - 扩展类加载器 - 根类加载器 \`\`\`java package java.lang.String; public class String{ public static void main(String args\[\]){ String s = new String(); } } // 双亲委派机制,安全机制,防止 // 自定义String 希望能够覆盖源码String 但是类加载的时候,app类加载器--》扩展类加载器---》根类加载器,跟类加载器会调用源码的String,集自己写String不能覆盖源码 \`\`\` !\[虚拟机的内部结构\](https://i.loli.net/2020/09/15/AUFO8aPsS7VHnlD.jpg) # 堆,方法区,栈 !\[img\](https://i.loli.net/2020/09/15/X6QhWUbtG14f2YC.jpg) # Native - 本地方法,集Native方法,调用时进入本地方法栈,java以不能管理,会调用JNI - 本地方法接口JNI ----\>本地方法库(C++,python等) # 计数器 每个线程一个计数器,指向下一条指令 # 方法区 - 所有线程共享 - 静态变量,静态方法,常量,成员方法,类信息(构造方法,接口定义),运行时常量池 - 常量池,对象的默认属性就是在常量池中 - 存放类与接口的常量, - \`\`\`java public class Student{ public String name = "xxx"; public static void main(String args\[\]){ new String(); // 此时创建的对象,它的name就是在常量池中 } } \`\`\` # java栈 - 8大基本类型+对象引用+实例的方法 - 主方法程序入栈,执行,调用其他方法时,其他方法再入栈执行,执行完返回,正在执行的方法在栈顶 - 栈满了,StackflowError,一般是200层 # 堆 - JVM分类 - sun 热点虚拟机 - jrockit,最快的jvm - IBM,J9VMJIT - jvm只有一个heap,大小可以调节,默认:实际使用1/64,试图申请内存的1/4(最大内存), - -Xms1024m -Xmx1024m - 堆内存细分 - 新生代 - 8:1:1----》伊甸园,幸存区0,幸存区1 - 老生区 - 永久区 - 1.6 :永久代,常量池在方发区 - 1.7:永久代,常量池位于堆 - 1.8:元空间,方发区位于这里 - 存放java运行时环境,以及方法区的常量池等 - 逻辑上存在,物理上不存在 - 无垃圾回收 - 若第三方jar很多,Tomcat部署应用过多,动态生成反射类过多,可能会OOM !\[image-20200915221556463\](https://i.loli.net/2020/09/15/9kMr4UbOKqXIVAN.png) - 垃圾回收都在伊甸园,老生区 - 伊甸园满了---》对伊甸园轻GC---\>进入幸存区----》也满了---》对伊甸园,幸存区重GC-----》进入养老区---》又满了----》OOM - 但进入老生区对象很少,因为大多是临时对象 # Jprofiler - 内存分析工具 - idea使用 - 安装jprofiler插件 setting 指向 指向程序jprofiler.exe - 下载jprofiler.exe - dump - 添加启动参数 -XX:+HeapDumpOnOutOfMemoryError # GC算法 - 引用计数法,循环引用无法解决(不常使用) - 复制算法(浪费一个幸存区,复制比较费时,存活度较低时常用) - 伊甸园满了-》轻GC---》到幸存区0(随机选一个) - 伊甸园又满了---》轻GC--》存回对象会放到幸存区1,且就会把幸存区0的复制到幸存1,幸存0变为空 - 再此GC时,存活对象--》0,幸存1也复制到0 - 经历了15次GC,进入养老区, 可调参数 - 标记清除(2次扫描费时间,会产生碎片,但不浪费空间) - 扫描对象,标记活的对象 - 清除没标记的 - 标记清除压缩 - 标记清除再此扫描,整理碎片 - 总结 - 新生代:存活率低,适用复制算法 - 老生代:标记清除或标记清除压缩 # JMM - java内存模型 - 缓存一致性协议,定义数据读写规则 - 线程操作共享变量时,不能保证及时刷新入内存,volilate关键字可以保证及时刷新到内存 - 定义了8种指令的使用规则