JVM内存模型_gvm内存模型-程序员宅基地

技术标签: JVM  java  JVM内存模型  深入理解JVM  

Java在诞生之初就提出了"Write once,Run Anywhere"的口号,而这些都得益于JVM(Java Vritual Machine),可以提前在不同的运行环境(linux或windows等)上安装JDK之后,就可以让同一份代码在任何地方运行了。而这里的JDK(Java Development Kit)是Java语言、Java虚拟机和Java类库的统称。

一、JDK体系结构与Java跨平台特性

1.1 JDK体系结构

JDK是一个非常庞大的体系,里面包含了JVM、Java SE API(核心类库)、常用工具(javac等)以及Java语言等等一系列内容,其具体的体系结构图如下所示:

1.2 Java跨平台特性

Java的跨语言特性在文章开始已经提过了,通过在不同系统安装对应的JDK(主要是JVM)版本就可以实现,大概如下图所示:

二、JVM整体结构与内存模型

2.1 JVM整体结构

JVM称为Java虚拟机,作为一个虚拟机它首要的功能就是对应用程序的线程等分配内存空间,而JVM还要负责加载类、解析执行编译后的字节码文件,所以整个JVM主要就包含了运行时数据区、类加载子系统和字节码执行引擎。

大概的结构如下图所示:

在Java虚拟机外部,还有一些本地方法接口,这些接口也是JVM经常需要调用。

2.2 内存模型

Java虚拟机的运行时数据区显然是在内存中的,所以这一部分也成为JVM的内存模型,这里要与JMM(Java内存模型)区分开。

内存模型主要包含五部分的内容:堆、栈、本地方法栈、方法区(元空间)、程序计数器。

:JVM管理的最大一块内存空间,它是所有线程所共享的一块区域。在虚拟机启动的时候创建,该区域的唯一目的就是为了存放对象实例,几乎所有通过new创建的实例对象都会被分配在该区域。

栈(虚拟机栈):也可以称为虚拟机线程栈,它是JVM中每个线程所私有的一块空间,每个线程都会有这么一块空间。它的生命周期是与线程的生命周期是绑定的。虚拟机栈描述了Java中方法执行时的内存模型,即每个方法被执行的时候,线程都会在自己的线程栈中同步创建一个栈帧(Stack Frame),用于存放局部变量表、操作数栈、动态连接和方法出口等信息,每个方法从调用到完成的过程,就对应着一个栈帧在线程栈中从入栈到出栈的过程。

本地方法栈:本地方法栈与虚拟机栈的作用是相似,不同的是虚拟机栈为JVM执行的Java方法服务,而本地方法栈为JVM调用的本地方法服务。HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一。

程序计数器:只需要占用一小块的内存空间,每个线程都会有自己独立的程序计数器,主要功能就是记录当前线程执行到哪一行指令了,可以看作是当前线程所执行的字节码行号指示器。

方法区(元空间):在JDK 8之前,方法区也称之为永久代,这部分区域与堆一样,是所有线程所共享的,它主要用于存放被虚拟机加载的类型信息、常量、静态变量以及即时编译器编译后的代码缓存等数据。对于一个Class文件,除了版本、字段、方法、接口等描述信息外,还有常量池表,在上一篇文章《JVM类加载机制》中提到过,主要用于编译器生成的各种字面量和符号引用,而这部分内容在Class文件加载后是存放在方法区的运行时常量池中。这个运行时常量池自然还包括了字符串常量池,但需要注意的是,在JDK 7以后的版本中,字符串常量池和静态变量等被移至到了Java堆区,而到了JDK 8,抛弃了之前永久代的概念,通过在本地内存中实现了元空间(Meta-space)来代替永久代,并把JDK 7中永久代剩余内容(主要是类型信息)全部移至到了元空间

所以,方法区是使用直接内存来实现,这与堆是不一样的,也就是堆和方法区用的并不是同一块物理内存。

直接内存:直接内存并不是JVM运行时数据区的一部分,其分配不会受Java堆大小的限制。

下面以一个列子来演示JVM内存模型的各个部分,创建一个测试类如下:

public class Test {
    

    public int compute(){
    
        int a = 4;
        int b = 5;
        int c = a * b * 6;
        return c;
    }

    public static void main(String[] args) {
    
        Test test = new Test();
        int compute = test.compute();
        System.out.println(compute);
    }
}

将Test类编译之后,然后在控制台通过javap -c Test.class命令输出Class文件对应的字节码指令,下面主要分析compute()方法的字节码指令,结合JVM的内存模型。

public int compute();
	Code:
        0: iconst_4
        1: istore_1
        2: iconst_5
        3: istore_2
        4: iload_1
        5: iload_2
        6: imul
        7: bipush        6
        9: imul

下面是执行Test的main方法时,线程栈的模型,下面结合下面的模型和字节码指令来介绍运行时数据区的各个模块。
在这里插入图片描述

当执行Test类的main方法时,首先会将Test.class文件加载进JVM的方法区,主要有常量池和方法定义,而常量池中此时包含一个compute()的符号引用,而在执行main方法,当调用compute()方法时,会将compute()的符号引用变成该方法具体在方法区的内存地址(直接引用),因为这个过程是在程序运行时发生的,所以称为动态链接

在执行main()compute()方法时会分别在main线程栈中创建两个栈帧,因为main()先调用,所以其栈帧处于栈的底部。

通过compute()内存地址找到该方法包含的字节码指令就可以执行compute()方法了。

1、iconst_4表示将int类型数值4压入操作数栈中,此时compute()栈帧中的操作数栈中就只有一个数字4

2、istore_1表示将操作数栈顶的int类型数值放入到局部变量表的第二个槽位中(出栈),此时操作数栈就没有元素了。

注:局部变量表中,是以槽位为基本单位来存储数值,第一个槽位的索引下标为0,且存放的局部变量为当this引用

3、iconst_5表示将int类型数值5压入操作数栈中

4、istore_2表示将操作数栈顶的int类型数值放入到局部变量表的第三个槽位中

5、iload_1表示将局部变量表的第二个槽位中int类型的数值放入到操作数栈的栈顶

6、iload_2表示将局部变量表的第三个槽位中int类型的数值放入到操作数栈的栈顶

7、imul表示将操作数栈的元素全部出栈交给CPU进行乘法运算,然后再将运算结果压入操作数栈的栈顶

第七步完成后,此时操作数栈里面的数值只有一个20

8、bipush 6表示将单字节常量6放入到操作数栈的栈顶

9、imul将操作数栈中的int类型的元素20和6出栈交给CPU进行乘法运算,然后将计算结果120压入操作数栈的栈顶

10、istore_3表示将操作数栈顶的int类型数值放入到局部变量表的第四个槽位中

11、iload_3表示将局部变量表的第四个槽位中int类型的数值放入到操作数栈的栈顶

12、ireturn表示从当前方法返回int类型的数值,即操作数栈中的数值。

至此compute()方法就执行完成了,执行完之后,需要知道将返回到哪里去继续执行,这就是方法出口的作用,它会记录方法执行完之后,跳转到哪里。

注:对于这些常用的字节码指令可以参考周志明的《深入理解Java虚拟机》

三、JVM内存参数

JVM内存模型中的这些区域,都是有大小限制的,当然也可以通过JVM提供的参数来设置这些区域所占内存的大小。

补充:在JVM堆中的实例对象,会按照它们的年龄或大小分为新生代或老年代,而新生代的内存空间又分为Eden区和Survivor区,如下图所示:

至于为什么要这样划分内存空间,会在下篇文章介绍JVM的垃圾收集机制时详细介绍。

下面介绍这些常用参数的含义:

-Xss:表示每个线程栈的大小

-Xms:表示堆空间的初始可用大小,默认为物理内存的1/64

-Xmx:表示堆空间的最大可以大小,默认为物理内存的1/4(这个参数在应用程序中是一定要指定的)

-Xmn:表示新生代(年轻代)的大小

-XX:NewRatio:默认为2,表示新生代占年老代的1/2,占整个堆内存的1/3。

-XX:SurvivorRatio:默认为8,表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。

-XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。

-XX:MetaspaceSize: 指定元空间触发Full Gc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M左右,达到该值就会触发full gc进行类型卸载, 同时收集器会对该值进行调整: 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。

由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般推荐将这两个值都设置为256M。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sermonlizhi/article/details/124774141

智能推荐

四川成都二手房数据集可视化大屏全屏系统毕业设计应用-程序员宅基地

文章浏览阅读2.8k次,点赞17次,收藏18次。四川成都二手房数据集可视化大屏全屏系统毕业设计应用,大学生本科专科专升本成人教育毕业设计毕设开题报告模板,研究背景与意义、国内外研究现状、、研究思路与方法、研究内客和创新点、后台功能需求分析和前端功能需求分析、研究思路与研究方法、可行性、研究进度安排、论文(设计)写作提纲、主要参考文献,大学生本科专科专升本成人教育毕业设计毕设开题报告模板,研究背景与意义、国内外研究现状、、研究思路与方法、研究内客和创新点、后台功能需求分析和前端功能需求分析、研究思路与研究方法、可行性、研究进度安排、论文(设计)写作提纲

java/php/node.js/python英语学院学生选课微信小程序【2024年毕设】-程序员宅基地

文章浏览阅读892次,点赞22次,收藏18次。后台主要是管理员和教师,管理员功能包括首页、个人中心、学生管理、教师管理、课程类型管理、课程信息管理、选课信息管理、取消选课管理、管理员管理、系统管理等;教师功能包括首页、个人中心、课程信息管理、选课信息管理、取消选课管理等;springboot基于springboot架构的博客平台设计。springboot基于网络评论的旅馆预定网站的设计与实现。springboot基于微信小程序的校园跑腿平台。

CSP-J 2022复赛T2 解密--分析_[csp-j 2023] 一元二次方程-程序员宅基地

文章浏览阅读3k次,点赞6次,收藏6次。csp-j2022复赛 T2-解密详解_[csp-j 2023] 一元二次方程

探索LavaLite CMS:一款强大的开源内容管理系统-程序员宅基地

文章浏览阅读233次,点赞5次,收藏7次。探索LavaLite CMS:一款强大的开源内容管理系统项目地址:https://gitcode.com/LavaLite/cms项目简介LavaLite CMS 是一个基于PHP和MySQL构建的高效、灵活的开源内容管理平台。它的设计目标是为开发者提供一个简单易用且功能丰富的工具,以快速构建和管理网站内容。该项目在GitCode上开源,鼓励社区参与和贡献,旨在持续改进并满足多样化的Web开..._lavalite

DB Query Analyzer 6.02 is released, 71 articles concerned have been published-程序员宅基地

文章浏览阅读48次。DB Query Analyzer is presented by Master Genfeng, Ma from Chinese Mainland.It has English version named ‘DB Query Analyzer’ and Simplified Chinese version named.DB Query Analyzer is one of t...

C++实现登录注册(文件储存和读取)_c++类中登录的代码-程序员宅基地

文章浏览阅读1.3w次,点赞54次,收藏341次。C++实现登录注册,并将数据保存到文件(txt文档中)实现要求:1.如果不存在初始用户数据文件则创建用户数据文件2.实现完整的注册登录3.实现用户数据的自动保存和读取4.密码输入提供直接显示和隐式显示1.运行截图运行结果如下:2.实现代码代码如下:#include "iostream"#include "fstream"#include "string"#include <conio.h>using namespace std;#define SIZE 100_c++类中登录的代码

随便推点

如何在linux上下载各种常用安卓应用_麟卓卓懿下载-程序员宅基地

文章浏览阅读6.1k次。随着互联网的发展,在很多场合中或者工作中都会用到linux系统,但常用linux的小伙伴们都知道,linux对各个常用的安卓应用兼容性很差,基本上好多应用只有简易的网页版,例如微信、QQ、钉钉等,网页版的很多功能都没办法使用,这给我们的工作带来了很多不便。这里呢我就给大家推荐一个完美兼容linux系统环境的平台–麟卓卓懿应用商城。麟卓卓懿应用商城支持海量安卓应用无缝透明运行在Linux平台上,实现移动应用生态和桌面应用生态的完美结合。麟卓卓懿应用商城的应用中心中可以下载海量的安卓应用,并且应用种类多、平_麟卓卓懿下载

微信小程序node+vue+uniapp课程在线答疑学习答题考试系统_uni-app 考试系统-程序员宅基地

文章浏览阅读818次。系统主要分为管理员和学生、教师三部分,管理员服务端:首页、个人中心、学生管理、教师管理、课程资源管理、课程类型管理、学习记录管理、系统管理,教师服务端:首页、个人中心、课程资源管理、学习记录管理、试题管理、试卷管理、考试管理,学生客户端;首页、首页、课程资源、我的等功能,基本上实现了整个答题系统小程序信息管理的过程。本系统在一般答题系统小程序的基础上增加了最新信息的功能方便用户快速浏览,是一个高效的、动态的、相互友好的答题系统小程序。(2)减少维护人员的工作量以及实现用户对信息的控制和管理。_uni-app 考试系统

让wordpress博客首页、分类页 显示文章标题列表或摘要-程序员宅基地

文章浏览阅读445次。 最近买了个godaddy的150G的空间,准备用dede和wordpress做些小站,wordpress架起来以后,发布的文章都是全部展示在首页的,如果文章比较长的话,这样会使网站首页内容很长,所以一般情况我们都希望在首页上只显示文章标题和文章摘要。那么我们如何来实现这功能呢,查阅了一下后发现,其实这个很简单,具体做法如下: 首先找到wp-content/themes下你使用的模板目录,查...

Java基础_14字符串的方法和权限修饰符__泛型【重点】-程序员宅基地

文章浏览阅读785次,点赞26次,收藏15次。public 返回值类型 方法名字 (参数) {带有泛型的方案的语法格式public 返回值的类型 方法名字 (参数) {}无意义的占位符:可以是26个英文单词大写, 还可以是?开始中经常使用 T(Type) E(Element) K (key) V(value)?无参无返回值有参无返回值无参有返回值有参有返回值test(23);//T Intgertest("狗蛋");//T Stringtest('嘻');//泛型 代表各种类型的 广泛的类型。

时尚机密防线升级:迅软DSE助力时装企业应对终端泄密挑战-程序员宅基地

文章浏览阅读1.1k次,点赞32次,收藏25次。2.针对员工电脑文档操作行为及流转情况进行审计,包括文档创建、修改、复制、移动、重命名、删除、上传、下载等行为进行记录,并生成统计报表,及时发现员工违规操作行为。1.公司设计新款女装和时尚服饰,设计人员产生的图纸文档明文存放在电脑上,部分设计人员使用Mac电脑,图纸文档可以随意外传出去,存在泄密风险。1.针对员工电脑文档加密、申请解密、直接解密、审批解密、文档外发、全盘扫描加解密等行为进行记录,统计员工文档加解密操作行为。1.员工电脑禁止使用U盘随意拷贝文档,统一使用公司注册验证的U盘接入拷贝数据。

npm安装报错解决合集(一)_npm warn eresolve overriding peer dependency-程序员宅基地

文章浏览阅读8.1w次,点赞26次,收藏89次。在新版nodejs已经集成了npm,所以npm也都安装好了。可以通过输入下面命令来测试是否成功安装node -vnpm -v如果安装成功,都会出现版本号用npm -v测试,报错:node:internal/modules/cjs/loader:936 throw err; ^Error: Cannot find module 'D:\lcb\software\nodejs\node_modules\npm\bin\npm-cli.js' at Function.Module_npm warn eresolve overriding peer dependency

推荐文章

热门文章

相关标签