jvm系列(1)运行时数据区

1 JVM

1.1 JVM运行时数据区域

这里写图片描述

JDK 1.7 及以往的 JDK 版本中,Java 类信息、常量池、静态变量都存储在 Perm(永久代)里。类的元数据和静态变量在类加载的时候分配到 Perm,当类被卸载的时候垃圾收集器从 Perm 处理掉类的元数据和静态变量。当然常量池的东西也会在 Perm 垃圾收集的时候进行处理。

JDK 1.8 的对 JVM 架构的改造将类元数据放到本地内存中(元空间),另外,将常量池和静态变量放到 Java 堆里。HotSopt VM 将会为类的元数据明确分配和释放本地内存。在这种架构下,类元信息就突破了原来 -XX:MaxPermSize 的限制,现在可以使用更多的本地内存。这样就从一定程度上解决了原来在运行时生成大量类的造成经常 Full GC 问题,如运行时使用反射、代理等。

1.2 各区域介绍

1.2.1 程序计数器

一块较小的内存空间, 是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有”的内存。如果当前线程执行的是native方法,则其值为null。这个内存区域是唯一一个在虚拟机中没有规定任何OutOfMemoryError情况的区域。

1.2.2 Java虚拟机栈

stack

线程私有,每个线程对应一个Java虚拟机栈,其生命周期与线程同进同退。每个Java方法在被调用的时候都会创建一个栈帧,并入栈。一旦完成调用,则出栈。所有的的栈帧都出栈后,线程也就完成了使命。

**栈帧( Frame)**是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接 (Dynamic Linking)、 方法返回值和异常分派( Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。

1.2.3 本地方法栈

本地方法区和Java Stack作用类似, 区别是虚拟机栈为执行Java方法服务, 而本地方法栈则为Native方法服务, 如果一个VM实现使用C-linkage模型来支持Native调用, 那么该栈将会是一个C栈,但HotSpot VM直接就把本地方法栈和虚拟机栈合二为一。

1.2.4 堆

是被线程共享的一块内存区域,创建的对象和数组都保存在Java堆内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域。由于现代VM采用分代收集算法, 因此Java堆从GC的角度还可以细分为: 新生代(Eden区、From Survivor区和To Survivor区)和老年代。

heap

新生代

是用来存放新生的对象。一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收。新生代又分为 Eden区、SurvivorFrom、SurvivorTo三个区。

Eden区

Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。

SurvivorFrom

上一次GC的幸存者,作为这一次GC的被扫描者。

SurvivorTo

保留了一次MinorGC过程中的幸存者。

参数解释
参数 作用
-XX:InitialSurvivorRatio 新生代Eden/Survivor空间的初始比例
-XX:Newratio Old区 和 Yong区 的内存比例
MinorGC采用复制算法

MinorGC的过程(复制->清空->互换)

  1. eden、survicorFrom 复制到SurvicorTo,年龄+1

首先,把Eden和SurvivorFrom区域中存活的对象复制到SurvicorTo区域(如果有对象的年龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果SurvicorTo不够位置了就放到老年区);

  1. 清空eden、survicorFrom

然后,清空Eden和SurvicorFrom中的对象;

  1. SurvicorTo和SurvicorFrom互换

    最后,ServicorTo和SurvicorFrom互换,原ServicorTo成为下一次GC时的SurvicorFrom区。

老年代

主要存放应用程序中生命周期长的内存对象。

你可能感兴趣的:(jvm系列,JAVA,JAVA基础知识,jvm,运行时数据区)