jvm内存模型

JVM


  1. jvm的位置

    image-20211020203230884

  2. jvm的体系结构

    image-20211020204736953

  3. 类加载器

    image-20211020212334319

    1 虚拟机自带的类加载器

    2 启动类 根加载器 :引导类加载器,Bootstrap ClassLoader 使用c/c++实现,用来加载java核心库

    3 扩展类加载器:Extension ClassLoader 使用java语言编写,父类为启动类加载器,从java.ext.dirs 系统属性所指定的目录中加载类库,从jdk安装目录jre/lib/ext 子目录下加载类库

    4 应用程序加载器:系统加载器,AppClassLoader 使用java 语言编写,负责加载环境变量classpath或java.class.path 指定路径下的类库。默认的类加载器,一般java引用的类都是由他来完成加载。

  4. 双亲委派机制

    为了安全,在我们进行类加载的时候,会一层一层的往上委托,在上层父类包中找不到,才一层一层往下找。

  5. 沙箱安全机制

    就是一种保护机制,防止外来的程序损害电脑。

    基本组件:

    • 字节码校验器:确保java 类文件遵循java语言规范。

    • 类装载器:类装载器在 防止恶意代码去干涉善意代码,守护了被信任的类库边界,将代码归入保护域,确定代码可有那些操作...这三个方面起作用

      装载器采用的机制是双亲委派模式。

    • 存取控制器:用户可以指定存取控制器控制核心api对操作系统的存取权限。

    • 安全管理器:实现权限控制,是核心api和操作系统之间的主要接口。

    • 安全软件包:允许用户为i自己的应用增加新的安全特性

  6. Native

    凡是带了native 关键字的,说明java的作用范围达不到了,会去调用底层c语言的库

    会进入 本地方法栈 调用 本地方法接口JNI 为了扩展java的使用,融合不同的语言

    它在内存区专门开辟了一块标记区域:Native Method stack 用来登记native方法

    java 程序驱动打印机,管理系统。

  7. PC寄存器

    Program Counter Register 程序计数器

    每个线程都有一个程序计数器,是线程私有的,就是一个指针,指针方法区中的方法字节码(用来存放指向像一条指令的地址,即将要执行的代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

  8. 方法区

    Method Area

    方法区是被所有线程共享的,所有字段的方法字节码,以及一些特殊的方法,如构造函数,接口代码也在此定义。简单来说,所有定义的方法的信息都保存在该区域,此区域属于共享区间

    静态变量,常量,类信息(构造方法,接口定义),运行时的常量池存放在方法区中,实例变量存放在堆内存中,和方法区无关。

    static final Class 常量池。

  9. 程序 = 数据结构+算法

    队列:先进先出 FIFO

    栈:就像一个桶 先进后出,后进先出 数据结构原文中是 模拟一个***弹夹,先进的后出。

    为什么main()方法先执行,最后结束。

    栈内存主管程序的允许,生命周期和线程同步,线程结束,栈内存也就是释放,对于栈来说,不存在垃圾回收问题,一旦线程结束,栈就over。

    image-20211020233806667

    栈中存放 8 大数据类+引用对象+实例的方法。

    栈+ 堆+ 方法区 的交互

    image-20211020234522749

  10. 三种JVM

    • sun公司 HotSpot 我们学习的

    • BEA JRockit

    • IBM J9 VM

  11. Heap 一个jvm只有一个堆内存,堆内存的大小是可以调节的。

    类加载器读取了类文件后,一般把类,方法,常量,变量...保存我们所有引用类型的真实对象:

    堆内存中还细分为三个区域:

    1. 新生区

      一个类 诞生和成长的地方,也可能是死亡的地方。

      伊甸园,所有对象都是在伊甸园区new出来的

      幸存者区(0,1)

      在伊甸园区如果这个对象没有被引用了,就会触发轻GC,存活下来的类就存放在幸存区中。

    2. 养老区

      当幸存区里也满了 就会触发重GC,将伊甸园和幸存区进行清理,存活下来的才保存到养老区。

      养老区也满了,就会报oom

    3. 永久区

      这个区域常驻内存,用来存放JDK自身携带的Class对象,Interface元数据,存储的是java运行时的一些环境,或者类信息。不存在垃圾回收。

      关闭虚拟机才会释放这个区域的内存

      只有一个启动类加载了大量的第三方jar包,Tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载,直到内存满了,就会出现OOM;

      jdk1.6 :永久代 常量池在方法区

      jdk1.7 :永久代 慢慢退化了,去永久代 常量池在堆中

      jdk1.8 : 无永久代,常量池在元空间

      image-20211021110632393

      GC 垃圾回收 主要是在伊甸园区和养老区

      堆内存满了,就会报OOM

      在jdk8以后,永久存储区叫 元空间

    image-20211021113734062

    持久代也叫 “非堆”

    public class Test004 {     public static void main(String[] args) {         long l = Runtime.getRuntime().maxMemory();//返回虚拟机试图使用的最大内存         long l1 = Runtime.getRuntime().totalMemory();         //返回虚拟机试图使用的最大内存         System.out.println(l/(double)1024/1024 + "mb");         //jvm 总内存         System.out.println(l1/(double)1024/1024 + "mb");      } } 

    指定内存大小

    image-20211021162315236

    image-20211021162326723

    OOM:

        1 常识扩大堆内存看结果

        2 分析内存,看一下那个地方出现了问题(专业工具)

    元空间:逻辑上存在,物理上不存在

  12. 堆内存调优

    使用JPROFILER软件进行 对堆内存的一个调优。

  13. GC,

    1 每次gc都会把活得对象移到幸存区,一旦伊甸园区被GC,就会空。

    2 为了保证幸存区to 为空 存区to和存区from会交换位置,并将对象都保存到一个幸存区中,那么剩下那个空的就会变为幸存区to。

    3 当一个对象经历了15此GC(可以设置次数:-XX:MaxTenuringThreshold=5),都还没有被回收,就会被放入老年区。

    image-20211021195930333

    好处:没有内存的碎片

    坏处:浪费了内存空间,to空间一直是空的。

    复制算法的最佳使用场景:对象的存活率较低。

    标记清除算法:第一次扫描将活着的对象进行标记,第二次扫描没有标记的对象直接清除。

    缺点:两次扫描浪费时间。会产生内存碎片。不需要额外的空间。

    标记压缩:再次扫描,将存活的对象移到一段

    缺点:虽然防止了碎片产生,但是任然浪费时间。

  14. JMM

    java Memory model

    1. java内存模型

    2. 缓存一次性协议,用于定义数据读写的规则

      JMM定义了线程和住内存之间的抽象关系:线程之间的共享变量存储在主内存中,内阁线程有一个私有本地内存。

      image-20211021202233749

    Volatile:可见性,不保证原子性,禁止指令重排(使用内存屏障来实现的,store屏障将工作内存中的变量刷新到主内存和local屏障从主内存中读取共享变量。)

  15. 总结

:像一个***弹夹,先进先后出。不存在GC,只有线程运行结束才会释放。主要存放的是八大数据类型+对象的引用+实例的方法,管理线程生命周期和线程同步。

本地方法栈(Native):Native 指向的是底层语言编写的指令(汇编,c/c++语言),调用本地方法接口JNI,可以扩展java,融合其他语言。

程序计数器:是每个线程私有的,就是一个指针,用来指向方法区中方法的字节码(用来指向程序即将要指向的指令的下一个地址),占用的内存非常小,可以忽略不计。

方法区:被所有线程共享,所有字段的字节码,特殊的方法如构造函数,接口代码,所有定义的方法和信息都保存在方法区。静态常量+常量+类信息+运行时常量池。

:GC主要是在堆中存在,对象刚new出来存放在伊甸园区,经过轻gc放入幸存区from中,每次gc保证幸存区to中不存放对象,当然两个幸存区会相互切换,保证空的幸存区为幸存区to,经过15次gc还没有被回收的对象存放到永久区(1.7),1.8以后叫元空间。

可以设置次数 -XX:MaxTenuringThreshold

#学习路径##Java#
全部评论
养老区 哈哈哈哈哈哈
点赞
送花
回复 分享
发布于 2021-11-02 11:48

相关推荐

1 20 评论
分享
牛客网
牛客企业服务