Java虚拟机一:运行时数据区域

时间:2022-12-09 13:27:37

  java虚拟机在执行java程序的过程中,会把内存划分为若干个不同的数据区域。每个区域都有各自的用途,创建和销毁时间,按照《java虚拟机规范(Java SE 7 版)》的规定,虚拟机运行时数据区域主要有以下几种:

Java虚拟机一:运行时数据区域

1.程序计数器

  程序计数器是很小的一块内存区域,可以看做是当前线程所执行字节码的行号指示器。在虚拟机的概念模型中,字节码解释器工作时就是通过改变程序计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能均依赖于程序计数器。在多线程中,每个线程都有一个独立的程序计数器,每个线程的程序计数器之间互不影响,即“线程私有”。同时,程序计数器是java虚拟机规范中唯一一个没有规定OutOfMemoryError的区域。

2.java虚拟机栈

  虚拟机栈描述的是java方法执行的内存模型,每个方法在执行时候都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每个方法从被调用执行到执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。虚拟机栈也是线程私有的。在Java虚拟机规范中,虚拟机栈有两种异常状况:

(1)线程请求的栈深度大于虚拟机栈所允许的深度,将抛出*Error异常;

(2)如果虚拟机栈可以动态扩展,但扩展时无法申请到足够的内存,或者在创建新线程时候没有足够的内存去创建虚拟机栈,就会抛出OutOfMemoryError异常。

3.本地方法栈

  本地方法栈和虚拟机栈的作用类似,区别在于java虚拟机栈支持Java方法执行,而本地方法栈则支持native方法执行。有些虚拟机直接将java虚拟机栈和本地方法栈合二为一,本地方法栈的异常情况与java虚拟机栈的内存一致,即:

(1)线程请求的栈深度大于本地方法栈所允许的深度,将抛出*Error异常;

(2)如果本地方法栈可以动态扩展,但扩展时无法申请到足够的内存,或者在创建新线程时候没有足够的内存去创建本地方法栈,就会抛出OutOfMemoryError异常。

4.java堆

  java堆是Java虚拟机所管理的内存中最大的一块,它是被所有线程所共享的内存区域,在虚拟机启动时候创建。java堆是供所有类实例和数组分配内存的区域,也是垃圾收集器管理的主要区域,因此很多时候也被称为“GC堆”。从内存回收的角度来看,由于收集器基本都采用分代收集算法,所以Java堆还可以细分为新生代(Young Gen)和老年代(Old Gen)。新生代又可以继续分为Eden空间,From Survivor空间,To Survivor空间。如下图:

Java虚拟机一:运行时数据区域

  Java堆的大小可以是固定的,也可以是随着程序执行动态扩展,并在不需要过多空间时候自动收缩。且Java堆所使用的内存不需要保证是连续的。如果实际所需的堆超过了自动内存管理系统所能提供的最大容量,java虚拟机将会抛出一个OutOfMemoryError异常。

  Java堆常用调节参数:

   -Xms128M :设置初始堆大小为128M
   -Xmx512M :设置最大堆大小为512M
   -XX:NewSize=n :设置年轻代大小;
   -XX:NewRatio=n :设置年轻代和年老代的比值,如设置为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代的1/4;
   -XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值(年轻代分成1个Eden Space和2个Suvivor Space),如设置为3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5;

5.方法区

  方法区和java堆一样,是所有线程共享的内存区域。它存储了每一个类的结构信息,例如运行时常量池,字段和方法数据,构造函数和普通方法的字节码内容,还包括一些在类,实例,接口初始化时用到的特殊方法。由于HotSpot虚拟机设计团队将GC分代扩展到了方法区,或者说使用“永久代”来实现方法区,这样HotSpot的垃圾收集器就可以像管理Java堆那样来管理方法区内存,故很多人将方法区称为永久代,但本质上两者不是等价的(Java8中,HotSpot对于方法区的实现从永久代变更为元空间Metaspace)对于其他虚拟机(如BEA JRockit,IBM J9等)而言是不存在永久代的。按照java虚拟机规范,当方法区不能满足内存分配请求时,java虚拟机将抛出OutOfMemoryError异常。

  方法区常用调节参数:

  java8之前(设置永久代):

   -XX:PermSize=64M  :设置持久代初始大小
   -XX:MaxPermSize=128M  :设置持久代最大允许分配大小。

  java8之后(设置元空间):  

   -XX:MetaspaceSize=8M :设置元空间大小为8M
   -XX:MaxMetaspaceSize=80M :设志元空间最大为80M
   -XX:MinMetaspaceFreeRatio=n :当进行过Metaspace GC之后,会计算当前Metaspace的空闲空间比,如果空闲比小于这个参数,那么虚拟机将增长Metaspace的大小。默认值为40,也就是40%
   -XX:MaxMetasaceFreeRatio=n :当进行过Metaspace GC之后, 会计算当前Metaspace的空闲空间比,如果空闲比大于这个参数,那么虚拟机会释放Metaspace的部分空间。默认值为70,也就是70%
   -XX:MaxMetaspaceExpansion=n :设置Metaspace增长时的最大幅度
   -XX:MinMetaspaceExpansion=n :设置Metaspace增长时的最小幅度

6.运行时常量池

  运行时常量池是方法区的一部分,是class文件中每一个类或者接口的常量池表在运行时的表现形式。在加载类和接口到虚拟机后,就创建对应的运行时常量池。如果构造运行时常量池所需要的内存空间超过了方法区所能提供的最大值,Java虚拟机就会抛出一个OutOfMemoryError异常。

  需要特别注意的是,运行时常量池和字符串常量池的区别,在jdk1.7之前,运行时常量池逻辑包含字符串常量池存放在方法区,此时hotspot虚拟机对方法区的实现为永久代。在JDK1.7 字符串常量池被从方法区拿到了堆中,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代。JDK1.8 hotspot移除了永久代引入元空间(Metaspace), 这时候字符串常量池还在堆中, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间(Metaspace)。

参考资料:

《深入理解Java虚拟机 JVM高级特性与最佳实践 第2版》

《Java虚拟机规范(Java SE 7)》

Java虚拟机一:运行时数据区域的更多相关文章

  1. Java虚拟机及运行时数据区

    1.Java虚拟机的定义 Java虚拟机(Java Virtual Machine),简称JVM.当我们说起Java虚拟机时,可能指的是如下三种不同的东西: 抽象的虚拟机规范 规范的具体实现 一个运行 ...

  2. Java虚拟机_运行时数据区

    Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途.各自的创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程启动 ...

  3. 【Java虚拟机】运行时数据区

    Java在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途.创建和销毁的时间,有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,有些则是与线程一一对应,随 ...

  4. 想买保时捷的运维李先生学Java性能之 运行时数据区域

    前言 不知道自己不知道,不知道自己知道,知道自己不知道,知道自己知道,目前处于知道自己不知道这个阶段,很痛苦啊,干了4年了运维,是一个坎.越来越发觉想要走得远,还是得扎根底.   一.运行时数据区域 ...

  5. Java虚拟机一 运行时数据区(栈、堆、方法区等)

    Java虚拟机的内存管理主要分两点:内存分配以及内存回收.· 一.内存分配图: 注: 所占区域的大小与实际的内存大小比例并无直接关系. 解读: 1.如图,分成两种颜色的内存区域,其中蓝色的是线程隔离的 ...

  6. 深入理解Java虚拟机(一) 运行时数据区划分

    前言:从我学Java的第一天开始,我的大学老师就告诉我 Java语言相比C.C++的语言有一个非常强大的功能,那就是自动内存管理:我们用Java编码时不需要申请或释放内存等,这些工作全部交由我们的Ja ...

  7. java虚拟机规范-运行时数据区

    前言 java虚拟机是java跨平台的基石,本文的描述以jdk7.0为准,其他版本可能会有一些微调. 引用 java虚拟机规范 数据类型 java总共有两种数据类型:基本类型和引用类型.java虚拟机 ...

  8. java虚拟机规范-运行时栈帧

    前言 java虚拟机是java跨平台的基石,本文的描述以jdk7.0为准,其他版本可能会有一些微调. 引用 java虚拟机规范 java虚拟机规范-运行时数据区 java内存运行时的栈帧结构 java ...

  9. Java虚拟机-运行时数据区域

    Java虚拟机管理的内存包括如图所示的运行时数据区域: 下面分别进行介绍: 1)程序计数器(Program Counter Register) 占用的内存空间比较小,主要作用就是标识当前线程执行的字节 ...

  10. 深入理解JAVA虚拟机之JVM性能篇---基础知识点(运行时数据区域)

    一. 运行数据区域划分 各个数据区域功能如下: 1. 程序计数器: 较小的一块内存空间,可以看做是当前线程所执行的字节码的行号指示器,每条线程都有一个独立的程序计数器,各条线程之间计数器互不影响,独立 ...

随机推荐

  1. Async和Await异步编程的原理

    1. 简介 从4.0版本开始.NET引入并行编程库,用户能够通过这个库快捷的开发并行计算和并行任务处理的程序.在4.5版本中.NET又引入了Async和Await两个新的关键字,在语言层面对并行编程给 ...

  2. AngularJs之四(作用域)

    一:angulaJs的作用域scope Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带.scope 是一个 JavaScript 对象,带有属性和方 ...

  3. Java 回调机制的理解

    // 在接口中声明一个处理耗时操作结果的回调方法. // Local 实现这个接口,实现处理耗时操作结果的回调方法. // Local 获得 Remote 对象,在子线程中调用 Remote 的处理耗 ...

  4. Export-XLSX PowerShell generate real Excel XLSX files without Excel and COM

    http://gallery.technet.microsoft.com/scriptcenter/Export-XLSX-PowerShell-f2f0c035

  5. 6.css文本样式

    文本样式,只要针对的是文本的效果和文本的方位,即文本样式和文本控制总结起来有一表中的属性可用: 属性名 说明 CSS 版本 text-decoration 装饰文本出现各种划线 1 text-tran ...

  6. maven项目配置Jetty服务器

    <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin ...

  7. bzoj2437

    会做jsoi那道game,这题就非常简单了吧 我们考虑空格的移动,显然,初始与空格位置距离为奇数的黑棋和距离为偶数的白棋并没有什么用, 空格不会移到那,我们直接把他们当作障碍,其他点我们当作可移动区域 ...

  8. AVL树插入和删除

    一.AVL树简介 AVL树是一种平衡的二叉查找树. 平衡二叉树(AVL 树)是一棵空树,或者是具有下列性质的二叉排序树:    1它的左子树和右子树都是平衡二叉树,    2且左子树和右子树高度之差的 ...

  9. Android中EditText显示明文与密文的两种方式

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 记录输入框显示.隐藏密码的简单布局以及实现方式. 效果图    代码分析 方式一 /**方式一:*/ private void sh ...

  10. 加载 AssetBundle 的四种方法

    [加载 AssetBundle 的四种方法] 1.AssetBundle.LoadFromMemoryAsync(byte[] binary, uint crc = 0); 返回AssetBundle ...