精华内容
下载资源
问答
  • jvm 内存模型

    万次阅读 多人点赞 2019-08-15 14:28:51
    2. jvm 内存模型划分 根据JVM规范,JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。 程序计数器(线程私有): 是当前线程锁执行字节码的行号治时期,每条线程都有一个独立的程序计数器...

    二. jvm 内存模型划分

    根据JVM规范,JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。
    这里写图片描述

    程序计数器(线程私有):
    是当前线程锁执行字节码的行号治时期,每条线程都有一个独立的程序计数器,这类内存也称为“线程私有”的内存。正在执行java方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果是Natice方法,则为空。

    java 虚拟机栈
    也是线程私有的。
    每个方法在执行的时候也会创建一个栈帧,存储了局部变量,操作数,动态链接,方法返回地址。
    每个方法从调用到执行完毕,对应一个栈帧在虚拟机栈中的入栈和出栈。
    通常所说的栈,一般是指在虚拟机栈中的局部变量部分。
    局部变量所需内存在编译期间完成分配,
    如果线程请求的栈深度大于虚拟机所允许的深度,则StackOverflowError。
    如果虚拟机栈可以动态扩展,扩展到无法申请足够的内存,则OutOfMemoryError。
    本地方法栈(线程私有)
    和虚拟机栈类似,主要为虚拟机使用到的Native方法服务。也会抛出StackOverflowError 和OutOfMemoryError。

    Java堆(线程共享)
    被所有线程共享的一块内存区域,在虚拟机启动的时候创建,用于存放对象实例。
    对可以按照可扩展来实现(通过-Xmx 和-Xms 来控制)
    当队中没有内存可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。
    方法区(线程共享)
    被所有方法线程共享的一块内存区域。
    用于存储已经被虚拟机加载的类信息,常量,静态变量等。
    这个区域的内存回收目标主要针对常量池的回收和堆类型的卸载。

    3.jvm 1.8 内存区域划分
    这里写图片描述

    程序计数器
    每个线程一块内存,指向当前正在执行的字节码的行号。如果当前线程是native方法,则其值为null。

    ps(程序计数器内存划分)
    因为处理器在一个确定是时刻只会执行一个线程中的指令,线程切换后,是通过计数器来记录执行痕迹的,因而可以看出,程序计数器是每个线程私有的。
    如果执行的是java方法,那么记录的是正在执行的虚拟机字节码指令的地址的地址,如果是native方法,计数器的值为空(undefined)。

    Java虚拟机栈

    这里写图片描述

    ps: 虚拟机栈中的名词解释

    局部变量表:
    存放编译期可知的各种基本数据类型、对象引用类型和returnAddress类型(指向一条字节码指令的地址:函数返回地址)。
    long、double占用两个局部变量控件Slot。
    局部变量表所需的内存空间在编译期确定,当进入一个方法时,方法在栈帧中所需要分配的局部变量控件是完全确定的,不可动态改变大小。
    异常:线程请求的栈帧深度大于虚拟机所允许的深度—StackOverFlowError,如果虚拟机栈可以动态扩展(大部分虚拟机允许动态扩展,也可以设置固定大小的虚拟机栈),但是无法申请到足够的内存—OutOfMemorError。

    操作数栈:
    后进先出LIFO,最大深度由编译期确定。栈帧刚建立使,操作数栈为空,执行方法操作时,操作数栈用于存放JVM从局部变量表复制的常量或者变量,提供提取,及结果入栈,也用于存放调用方法需要的参数及接受方法返回的结果。
    操作数栈可以存放一个jvm中定义的任意数据类型的值。
    在任意时刻,操作数栈都一个固定的栈深度,基本类型除了long、double占用两个深度,其它占用一个深度
    动态连接:
    每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。这些符号引用,一部分会在类加载阶段或第一次使用的时候转化为直接引用(如final、static域等),称为静态解析,另一部分将在每一次的运行期间转化为直接引用,这部分称为动态连接。

    方法返回地址:
    当一个方法被执行后,有两种方式退出该方法:执行引擎遇到了任意一个方法返回的字节码指令或遇到了异常,并且该异常没有在方法体内得到处理。无论采用何种退出方式,在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行。方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态。一般来说,方法正常退出时,调用者的PC计数器的值就可以作为返回地址,栈帧中很可能保存了这个计数器值,而方法异常退出时,返回地址是要通过异常处理器来确定的,栈帧中一般不会保存这部分信息。
    方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,如果有返回值,则把它压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面的一条指令。


    堆时JVM内存占用最大,管理最复杂的一个区域。唯一的途径就是存放对象实例:所有的对象实例以及数组都在堆上进行分配。jdk1.7以后,字符串常量从永久代中剥离出来,存放在堆中。堆具有进一步的内存划分。按照GC分代手机角度划分
    这里写图片描述
    老年代:2/3的堆空间
    年轻代:1/3的堆空间
    eden区:8/10 的年轻代
    survivor0: 1/10 的年轻代
    survivor1:1/10的年轻代

    元数据区域
    元数据区域取代了1.7版本及以前的永久代。元数据和永久代本质上都时方法区的实现。方法区皴法虚拟机加载的类型西,静态变量,常量数据。
    参数设置:-XX:MetaspaceSize=18m
    -XX:MaxMetaspaceSize=60m
    直接内存
    java.nio 中使用DirectBuffer相关使用(此处未完待续。。。。。。。。。)

    展开全文
  • JVM内存模型

    2018-12-02 15:38:29
    JVM 内存模型整理
  • JVM 内存模型

    热门讨论 2021-05-18 22:54:00
    1 什么是 JVM 内存模型 JVM 需要使用计算机的内存,Java 程序运行中所处理的对象或者算法都会使用 JVM 的内 存空间,JVM 将内存区划分为 5 块,这样的结构称之为 JVM 内存模型。 2 JVM 为什么进行内存区域划分 ...

    1 什么是 JVM 内存模型

    JVM 需要使用计算机的内存,Java 程序运行中所处理的对象或者算法都会使用 JVM 的内

    存空间,JVM 将内存区划分为 5 块,这样的结构称之为 JVM 内存模型。

    2 JVM 为什么进行内存区域划分

    随着对象数量的增加,JVM 内存使用率也在增加,如果 JVM 内存使用率达到 100%,

    则无法继续运行程序。为了让 JVM 内存可以被重复使用,我们需要进行垃圾回收。为了提

    高垃圾回收的效率,JVM 将内存区域进行了划分

    3 JVM 内存划分

    JVM 按照线程是否共享将内存首先分成两大类

    线程独享区

    ​ 只有当前线程能访问数据的区域,线程之间不能共享

    ​ 线程独享区随线程的创建而创建,随线程的销毁而被回收

    线程共享区

    ​ 所有线程都可以访问的区域,

    ​ 当线程被销毁的时候,共享区的数据不会立即回收,需要等待达到垃圾回收的阈(yu)

    ​ 值之后才会进行回收。

    在这里插入图片描述

    在这里插入图片描述

    4 程序计数器

    程序计数器会记录当前线程要执行指令的内存地址,只占用一小部分内存区域,只记录一个

    地址,所以我们认为程序计数器是不会出现内存溢出问题的分区

    5 本地方法栈

    Java 中有些代码的实现是依赖于其他非 Java 语言的(C++),本地方法栈存储的是维护

    非 Java 语句执行过程中产生的数据,一般我们认为本地方法栈不会出现内存的问题。

    6 虚拟机栈

    6.1 虚拟机栈的作用

    存放当前线程中所声明的变量,包括基本数据类型的数据和引用数据类型的引用。

    基本数据类型和引用数据类型划分的标准:

    基本数据类型:

    变量在声明的时候,能够确认占用内存的大小。

    引用数据类型:

    变量在声明的时候,不能确认占用内存的大小。

    引用数据类型将值的引用存放到虚拟机栈中,而对象存放在堆内存中,引用数据类型占用 4

    个字节存放地址

    6.2 栈帧

    每一个线程都会对应一个虚拟机栈,线程中的每个方法都会创建一个栈帧,存放本次方法执

    行过程中所需要的所有数据。

    如果我们一个线程中有多个方法的嵌套调用,虚拟机栈会对栈帧进行压栈和出栈操作。正在

    执行的方法一定在栈顶,我们只能获取栈顶的栈帧,栈帧在虚拟机栈中先进后出。

    在这里插入图片描述

    6.3 栈帧的数据结构

    局部变量

    存放当前方法的局部变量,基本数据类型存值,引用数据类型存堆内存地址。

    操作数栈

    对方法中的变量提供计算的区域。

    常量数据的引用

    常量数据会存放到方法区的常量池中,不管是基本数据类型还是引用数据类型都会存放常量

    池的地址

    方法返回值的地址

    方法返回数据会存到计算机内存的寄存器中。

    在这里插入图片描述

    6.4 虚拟机栈溢出异常

    由于栈帧调用的深度太深,会出现虚拟机栈溢出异常(SOF 异常)。一般手动方法的调用

    是不会出现这个异常的,如果出现这个异常 ,99%是由于递归。

    可以通过修改虚拟机栈的内存大小设置栈帧的最大深度,指令为:-Xss 虚拟机栈内存大小 。

    没设置-Xss虚拟机参数前,递归到7000多次就溢出报异常在这里插入图片描述

    在这里插入图片描述

    设置-Xss参数调大后10000多次递归次数才溢出报异常在这里插入图片描述

    一般栈帧深度达到 3000~5000 即可

    太小:虚拟机栈容易溢出。

    太大:每个线程占据的内存过大,影响线程数量。

    7 方法区

    在 java8 之后,我们把方法区称之为元空间(MetaSpace),方法区在逻辑上属于堆

    的一部分,但一些具体机制和堆有所区别,如:一些 JVM 的方法区是可以不进行垃圾回收

    的,关闭 JVM 时才会释放方法区内存。所以方法区还有一个别名叫非堆,目的是和堆分开。

    方法区会存储类信息、静态变量、常量(JDK8 之后不存放字符串常量)、本地机器指 令。

    如果加载大量 class 文件,也会造成方法区内存溢出,如一个 tomcat 运行 20~30 个 项目。

    展开全文
  • jvm内存模型

    2017-07-03 11:25:01
    jvm内存模型

    jvm内存模型:Java代码是运行在Java虚拟机之上的,由Java虚拟机通过解释执行(解释器)或编译执行(即时编译器)来完成,故Java内存模型,也就是指Java虚拟机的运行时内存模型。运行时内存模型,分为线程私有和共享数据区两大类,其中线程私有的数据区包含程序计数器、虚拟机栈、本地方法区,所有线程共享的数据区包含Java堆、方法区,在方法区内有一个常量池。java运行时的内存模型图,如下:

    作者:Gityuan
    链接:https://www.zhihu.com/question/19748817/answer/88610988
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    http://www.cnblogs.com/dingyingsi/p/3760447.html 深入理解java虚拟机部分

    http://blog.csdn.net/u012387062/article/details/49406447 详细介绍

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,987
精华内容 5,994
关键字:

jvm内存模型