JVM内存结构(Java 工程师成神之路·基础篇·JVM)

第一章 JVM内存结构

第一章 JVM内存结构

为什么要了解JVM内存管理机制

JVM自动的管理内存的分配与回收,这会在不知不觉中浪费很多内存,导致JVM花费很多时间去进行垃圾回收(GC)
内存泄露,导致JVM内存最终不够用

JVM内存结构

看图即可

  1. 方法区(也就是"持久代"),java8里彻底被移除,取而代之的是元数据区堆(附:元数据区 调节参数:-XX:MaxMetaspaceSize,如果不指定大小,极限情况下可能耗尽系统所有内存 元数据区是堆外的一块直接内存)
  2. 栈(在hotspot JVM中,JVM方法栈–Java虚拟栈,与本地方法栈是同一个)
  3. PC寄存器(程序计数器)
  4. 直接内存:直接向系统内存申请的一块内存区域,javaNIO会使用,速度优于java堆内存。- 隶属于物理内存,不属于JVM内存

注意点:

  1. 堆是GC的主要区域,方法区、直接内存也会发生GC
  2. 栈与PC寄存器是每个线程都会创建的私有区域,不会GC
  3. 直接内存使用速度由于堆内存,但是内存的申请速度低于堆内存

方法区

1.存放内容(类的信息、类static属性、方法、常量池)

  • 已经加载的类的信息(名称、修饰符等)
  • 类中的static变量
  • 类中的field信息
  • 类中定义为final常量
  • 类中的方法信息
  • 运行时常量池:编译器生成的各种字面量和符号引用(编译期)存储在class文件的常量池中,这部分内容会在 类加载之后进入运行时常量池

2.使用实例:反射,在程序中通过Class对象调用getName等方法获取信息数据时,这些信息数据来源于方法区。
3.所抛错误:方法区域要使用的内存超过了其允许的大小时,抛出OutOfMemoryError
4.内存回收的主要目标:

  1. 对类的卸载(这也是为什么很多企业使用velocity等模板引擎做前端而不是使用jsp的原因之一)
  2. 针对常量池的回收 针对常量池的回收
    5.总结:
  3. 类中的static变量会在方法区分配内存,但是类中的实例变量不会(类中的实例变量会随着对象实例的创建一起分配在堆中,当然若是基本数据类型的话,会随着对象的创建直接压入操作数栈)
  4. 关于方法区的存放内容,可以这样去想所有的通过Class对象可以反射获取的都是从方法区获取的(包括Class对象也是方法区的,Class是该类下所有其他信息的访问入口)
    6.注意:常量池在jdk1.6在方法区;在jdk1.7在堆

1.存放内容(类的信息、类static属性、方法、常量池)

  1. 对象实例(类中的实例变量会随着对象实例的创建一起分配在堆中,当然若是基本数据类型的话,会随着对象的创建直接压入操作数栈)
  2. 数组值

2.使用实例:

  1. 所有通过new创建的对象都在这块儿内存分配,具体分配到年轻代还是年老代需要根据配置参数而定(新建对象直接分配到年老代有两种情况,看下边)

3.所抛错误:

  1. OutOfMemoryError:在堆中没有内存完成实例分配(关于实例内存的分配,之后再说),此时堆内存已达到最大无法扩展时。

4.内存回收的主要目标:

  1. 对类的卸载(这也是为什么很多企业使用velocity等模板引擎做前端而不是使用jsp的原因之一)
  2. 针对常量池的回收 针对常量池的回收
    5.调节参数:
  3. Xmx:最大堆内存,默认为物理内存的1/4但小于1G
  4. -Xms:最小堆内存,默认为物理内存的1/64但小于1G
  5. -XX:MinHeapFreeRatio,默认当空余堆内存小于最小堆内存的40%时,堆内存增大到-Xmx
  6. -XX:MaxHeapFreeRatio,当空余堆内存大于最大堆内存的70%时,堆内存减小到-Xms

注意点

  • 每条线程都会分配一个栈,每个栈中有多个栈帧(每一个方法对应一个栈帧)
  • 线程创建的时候创建一个线程的java栈
  • 每个方法在执行的同时都会创建一个栈帧,每个栈帧用于存储当前方法的局部变量表、操作数栈等,具体查看本文第一个图,每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程,说的更明白一点,就是方法执行时创建栈帧,方法结束时释放栈帧所占内存

存放内容

  • 局部变量表:八大基本数据类型数据、对象引用。该空间在编译期已经分配好,运行期不变。
  • 操作数栈:是执行引擎直接操作的部分

PC寄存器(程序计数器)

概念

  • -当前线程所执行的字节码的行号指示器,用于字节码解释器对字节码指令的执行。

    扫描二维码关注公众号,回复: 4541862 查看本文章
  • 多线程:通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个时刻,一个处理器(也就是一个核)只能执行一条线程中的指令,为了线程切换后能恢复到正确的执行位置,每条线程都要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储

在这里插入图片描述
本文转载自网络,如有侵权,请联系删除。 原文:https://www.cnblogs.com/java-zhao/p/5179836.html

猜你喜欢

转载自blog.csdn.net/H___mmm/article/details/85047312