JVM原理 | JVM内存模型

本文详细介绍了JVM内存模型,包括程序计数器、虚拟机栈、本地方法栈、堆和方法区。堆内存分为新生代和老年代,新生代采用复制算法,老年代存放长期存活的对象。方法区存储类信息和静态变量。此外,还讨论了类加载子系统、字节码执行引擎以及内存溢出和内存泄漏的概念。
摘要由CSDN通过智能技术生成

JVM内存模型

1. 概述

1.1 内存区

  1. 程序计数器 :

    1. 如果线程执行的是个java方法,用于存储下一条指令的地址。详细的说PC寄存器是用来存储指向下一条指令的地址,也就是即将将要执行的指令代码。由执行引擎读取下一条指令。

      即Java源代码不能直接去被执行,他得经过一次编译,编译成二进制字节码,里面的一行一行的东西都是JVM指令,Java虚拟机跨平台的基础就是这些JVM指令,这些指令在所有平台都是一致的。但这些指令也不能直接交给CPU执行,他必须要经过一个解释器,这个解释器也是Java虚拟机执行引擎的一个组件,他就专门负责把每一条JVM指令(比如getstatic)解释成为机器码,机器码就可以交给CPU执行。

    2. 如果为native【底层c++方法】,那么计数器为空。这块内存区域是虚拟机规范中唯一没有OutOfMemoryError的区域

  2. 虚拟机栈: java方法的执行和结束对应着栈帧的入栈和出栈,

    • 栈帧 : 用于存储局部变量表,操作方法行号,动态链接,方法出口等信息;

    • 局部变量表所需要的内存空间在编译期完成分配,当进入一个方法时,这个方法在栈中需要分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表大小。

    • Java虚拟机栈可能出现两种类型的异常:

      1. 线程请求的栈深度大于虚拟机允许的栈深度,将抛出StackOverflowError。
      2. 虚拟机栈空间可以动态扩展,当动态扩展是无法申请到足够的空间时,抛出OutOfMemory异常。
  3. 本地方法栈 : 本地方法栈是与虚拟机栈发挥的作用十分相似, 区别是虚拟机栈执行的是Java方法(也就是字节码.class)服务,而本地方法栈则为虚拟机使用到的native方法服务,可能底层调用的c或者c++, 我们打开jdk安装目录可以看到也有很多用c编写的文件,可能就是native方法所调用的c / c++代码。

  4. : 对于大多数应用来说,堆是java虚拟机管理内存最大的一块内存区域,主要存放一些实例对象(简单理解就是new出来的对象)因为堆存放的对象是线程共享的,所以多线程的时候也需要同步机制。因此需要重点了解下, 其中堆又分为:

    1. 年轻代 YoungGen

      1. Eden区
        • TLAB 区 ,详情可查看本文
      2. Survivor 0(survivor from)
      3. Survivor 1(survivor to)
      1. 新生代使用了复制算法
      2. 新生代为gc的重点对象,经官方测试70%对象都生命周期都会在新生代中完
      3. 新生代又分为了eden、survivor1、survivor2,对象创建先放在eden中,经过一定时间还幸存就会放在幸存者区
      4. 内存比例分默认为:8:1:1,分别对应eden,s0,s1
      5. 新生代收集器:Minor GC/Young GC
      6. 幸存区又分为from 和 to —谁为空谁为to ,始终都会有一个区域为空
      7. 幸存区不会主动进行垃圾回收,只会eden回收时才会附带进行gc
      8. 当在幸存区中的阈值达到了15后(默认15可修改)会自动进入老年代
      9. 当新生区(eden)出现了内存不足时,会进行YGC,那么会将没有指针的对象回收,还有指针引向的对象放入survivor1或者survivor2区域中,eden清空,数据放入一个survivor中。—当第二次进行gc那么会将eden数据放入另一个空的survivor中,并且将当前survivor中有效数据,放入空的survivor中,如此类推。
    2. 老年代 OldGen

      1. OldGen

    Java7及以前将堆空间逻辑上分成三部分:新生区+老年区+永久代
    Java8及以后将堆内存逻辑上分为:新生区+老年区+元空间

  5. 方法区: 保存在着被加载过的每一个类的信息;static变量信息也保存在方法区中;
    可以看做是将类(Class)的元数据,保存在方法区里;

    方法区是线程共享的;当有多个线程都用到一个类的时候,而这个类还未被加载,则应该只有一个线程去加载类,让其他线程等待;
    方法区的大小不必是固定的,jvm可以根据应用的需要动态调整。

img

1.2 类加载子系统

类加载器子系统作用?

类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。
ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。

类加载过程参考本文

1.3 字节码执行引擎

主要功能:

  1. 输入的是字节码文件,然后对字节码进行解析并处理,最后输出执行的结果。
  2. 修改程序计数器当前执行的位置;

2. 内存溢出和内存泄漏是什么

简述一下:

溢出: 所需要用的内存大于系统给的内存

泄漏: 某对象不用了但是没被回收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值