JVM(六) —— 运行时数据区之虚拟机栈的详细介绍
- 核心概述
- 堆空间代码演示
- 堆空间划分(重要)
一个Java程序运行起来是一个进程,这个进程对应着一个JVM实例,一个JVM实例对应着一个运行时数据区。而一个运行时数据区对应着一个方法区和一个堆。而一个进程中会有多个线程,这些线程会共享方法区和堆区。
核心概述
- 一个JVM实例只对应一个堆内存,对也是Java内存管理的核心区域。
- Java堆区在JVM启动的时候就被创建,齐空间大小也就确定了。是JVM管理的最大的一块内存空间。
- 堆内存大小是可以调节的,使用 -Xms 和-Xmx命令进行调节,其语法和栈空间大小一致。
- Java虚拟机规范规定,堆可以处于物理上不连续的内存空间中,但在逻辑上他应该是被视为连续的。
- 所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffer , TLAB)。
- 所有的对象实例几乎都在堆空间分配,也有一些特殊情况不在堆空间分配。(比如逃逸分析,栈上分配等,这部分会在后边详细说明)
- 数组和对象可能永远不会存储在栈上,因为栈帧中保存引用,这个引用指向对象或者数组在堆中的位置。
- 在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除。
- 堆是垃圾回收(GC)的重点区域。
堆空间代码演示
堆的空间大小使用-Xms 和-Xmx进行设置,其中-Xms表示的是Java启动的时候堆空间的大小,-Xmx表示的是堆空间最大的大小。
准备好我们的代码:
Test1 堆空间大小设置10M
public class Test1 {
// -Xms10m 和-Xmx10mpublic static void main(String[] args) {System.out.println("开始");try {Thread.sleep(10000000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("结束");}}
Test2 堆空间大小设置20M
public class Test2 {
// -Xms20m 和-Xmx20mpublic static void main(String[] args) {System.out.println("开始");try {Thread.sleep(10000000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("结束");}}
在启动之前我们要想设置堆空间的大小:
两个运行程序分别设置好,我们就可以启动了。
启动之后我们找到我们本机java的安装目录,进入bin目录,打开jvisualvm.exe就可以看到以下界面:
其中红框里边的就是我们刚刚启动的Java进程,双击就会打开:
红框中就可以看到我们刚刚设置的堆大小:10M。
我们再看看Visual GC界面,这里边就是我们对应的对里边各个细化的不同区域的堆空间占用大小。包括新生代,老年代等空间的大小和占用情况。这部分我们在后边会详细介绍,这里先让大家感受一下。当然,有效的同学打开之后没有Visual GC界面,是因为没有安装Visual GC插件,插件安装请看:安装Visual GC插件
堆空间划分(重要)
现代垃圾收集器大部分都基于分带手机理论设计。
Java7及之前的堆内存逻辑上分为三部分:新生区 + 养老区+永久代
- Young Generation Space 新生区 Young/new
- 又被划分为Eden区和Survivor区
- Tenure Generation Space 养老区 Old/Tenure
- Permanent Space 永久区 Perm
**
Java8及之后的堆内存逻辑上分为三部分:新生区 + 养老区+元空间
- Young Generation Space 新生区 Young/new
- 又被划分为Eden区和Survivor区
- Tenure Generation Space 养老区 Old/Tenure
- Meta Space 元空间 Meta
养老区 < = > 老年区 < = > 老年代
永久区 < = > 永久代
在逻辑上永久代是划分在堆空间的,事实上堆空间没有永久代,永久代或者说元空间是方法区具体的落地实现。
我是用的JDK是8版本,我们可以看一下刚刚jvisualvm,我们可以看到新生代,老年代和元空间各自的空间占用,但是新生代和老年代的空间已经占据了10M,元空间是占用了1G的大小。
我们也可以通过设置JVM参数来查看各个区域的内存信息和GC信息,使用-XX:+PrintGCDetails打印GC信息,设置好参数运行:
由于堆中的内容设计很多,堆的相关内容我会分为几个篇章进行介绍,这篇文章就先讲到这里,之后我会尽快更新后边的内容。
创作不易!请大家三连一下, 谢谢!