JVM之运行时数据区

 Java虚拟机在运行时管理的内存区域被称为运行时数据区。

  程序计数器: 也叫pc寄存器,每个线程会通过程序计数器记录当前要执行的字节码指令的地址。程序计数器在运行时是不会发生内存溢出的,因为每个线程只存储一个固定长度的内存地址。

  JAVA虚拟机栈:采用栈的数据结构来管理方法调用中的基本数据,先进后出,每一个方法的调用使用一个栈帧来保存。JAVA虚拟机栈随着线程的创建而创建,而回收则会在线程的销毁时进行。由于方法可能会在不同线程中进行,每个线程都会包含一个自己的虚拟机栈。

 栈帧的组成:

   1、局部变量表:是在运行过程中存放所有的局部变量。栈帧中的局部变量表是一个数组,数组中每一个位置称之为槽,long和double类型占2个槽,其他类型占用1个槽。实例方法中的序号为0的位置存放的是this,指的是当前调用方法的对象,运行时会在内存中存对实例对象的地址。

   2、操作数栈:是栈帧中虚拟机在执行指令过程中用来存放临时数据的一块区域。

   3、帧数据:主要包含动态链接、方法出口、异常表的引用。当前类的字节码指令引用了其他类的属性或方法时,需要将符号引用转换成对应的运行时常量池中的内存地址。动态链接就保存了编号到运行时常量池的内存地址的映射关系。

        方法出口是指在方法正确或异常结束时,当前栈帧会被弹出,同时程序计数器应该指向上一个栈帧中的下一条指令的地址。所以当前栈帧中需要存储此方法出口的地址。

        异常表存放的是代码中异常的处理信息,包含了异常捕捉的生效范围以及异常发生后跳转到的字节码指令位置。 

    如果栈帧过多,占用内存超过栈内存可以分配的最大大小就会出现内存溢出。如果我们不指定栈的大小,jvm将创建一个具有默认大小的栈。大小取决于操作系统和计算机的体系结构。 可以使用虚拟机参数 -Xss设置java虚拟机栈的大小。单位为字节(默认为字节,必须是1024的倍数)、k或kb、m或mb、g或gb格式: -Xss1024k 与-Xss类似,也可以使用-XX:ThreadStackSize调整标准来配置堆栈大小。 格式:-XX:ThreadStackSize=1024  。 hotshot虚拟机对栈的内存要求有最大最小限制。Windows(64位)下jdk8测试最小值为180k,最大值为1024m。

本地方法栈:

   JAVA虚拟机栈存储了JAVA方法调用时的栈帧,而本地方法栈存储的是c++编写的native本地方法的栈帧。在hotshot虚拟机中,JAVA虚拟机栈和本地方法栈实现上使用了同一个栈空间。

堆:

 一般JAVA程序中堆内存是空间最大的一块内存区域。创建出来的对象都存在于堆上。

 栈上的局部变量表中,可以存放堆上对象的引用。静态变量也可以存放堆对象的引用,通个静态变量就可以实现对象在线程之间的共享。堆内存大小有上限,会发生内存溢出。堆空间有3个需要关注的值:used total max。这3个值可以通过arthas的dashboard看到。 

used:指的是当前已使用的堆内存。      total:是JAVA虚拟机已经分配的可用堆内存。

max是java虚拟机可以分配的最大堆内存。

测试代码:

package org.example.heap;

import java.io.IOException;
import java.util.ArrayList;

public class OverFlowError {
    public static void main(String[] args) throws IOException {

        ArrayList<Object> objects = new ArrayList<>();
        while (true){
            System.in.read();
            System.out.println("添加一次");
            objects.add(new byte[1024*1024]);
        }
    }
}

  在arthas上通过 dashboard -n 1 命令输出一次面板信息

  在中间的Memory栏 就有 used   total   max   usage   GC这5栏信息。

也可以直接输入memory 命令,只查看Memory的信息。

随着堆中对象增多,used逐渐接近total的值。当total内存即将不足时,JAVA虚拟机会继续分配内存给堆,但total有上限,最大只能与max相等。并不是当used=max=total时,堆内存才会溢出。堆内存溢出判断条件比较复杂,在total快接近max时就会发生内存溢出,并不会相等。如果不设置虚拟机参数,max默认是系统内存的四分之一,total默认是系统内存的64分之一。在实际应用中一般都需要设置total和max的值。

要修改堆的大小,可以使用参数-Xmx(max最大值)和-Xms(初始的total)。单位:字节(默认,必须是1024的倍数)、k或kb、m或mb、g或gb。限制:Xmx必须大于2mb,Xms必须大于1mb。 语法:-Xmx值 -Xms值

 下面看个实例,通过虚拟机参数对上面的代码程序设置堆的使用限制:  -Xmx200m  -Xms200m

然后在次启动arthas(注意-Xmx不要设置的太小,否则都不够arthas启动的,arthas启动就会报错)查看memory面板

我们发现对应的max值并不是我们设置的200m,而是小于200m的192m。

为什么arthas中显示的heap堆大小小于咱们设置的大小呢?

arthas中的heap堆内存使用了JMX技术中内存获取方式,这种方式与垃圾回收器有关,计算的是可以分配对象的内存,而不是整个内存。

JAVA服务端程序开发时,建议将-Xmx和-Xms设置为相同的值,这样在程序启动后可使用的总内存就是最大内存,而无需向JAVA虚拟机再次申请,减少了申请并分配内存时间上的开销,同时也不会出现内存过剩之后的堆收缩的情况。

 

  方法区: (是一个虚拟概念,每款JAVA虚拟机上都各不相同,jdk8之后的版本,将方法区存放在元空间中,元空间位于操作系统维护的直接内存中,独立于JAVA虚拟机内存之外)。默认情况下只要不超过操作系统承受的上限,可以一直分配,可以使用-XX:MaxMetaspaceSize=值  将元空间最大大小进行限制(没有过高要求时,一般设为256m)。

方法区存放基础信息,线程共享,主要包括三部分内容:

 1、类的元信息:保存了所有类的基本信息(元信息),一般称之为InstanceKlass对象,在类的加载阶段完成。

 2、运行时常量池:保存了字节码文件中的常量池内容。通过编号查表方式找到常量,这种常量称为静态常量池。当常量池加载到内存中,可以通过内存地址快速定位到常量池中的内容,这种常量池称为运行时常量池。

 3、字符串常量池:保存了字符串常量。存储在代码中定义的常量字符串内容。

jdk7以前(不包括7)字符串常量池是属于运行时常量池的一部分,他们存储的位置一致。后续做了调整,jdk7后将字符串常量池拿到了堆中。(逻辑上,字符串常量池存在在方法区,但从物理存储地址看,是存放在堆中)jdk7及以后,静态变量和字符串常量池都是存放在堆中的。

下面看个例子:

package org.example.method;

public class StringTable {
    public static void main(String[] args) {
        String a="1";
        String b="2";
        String c="12";
        String d=a+b;
        System.out.println(c==d);
        String e="1"+"2";
        System.out.println(c==e);
    }
}

执行结果是c==d为false,c位于方法区的字符串常量池中,d是创建了一个String对象,存放在了堆中。查看字节码文件可以看出 在创建d时是用的new方法创建了一个对象,而c是定义了一个属性    

     c==e为true。e是直接引用的字符串常量池中的c的值。

下面我们在看个例子,先介绍一下string.inturn方法 作用是可以手动的将字符串放入字符串常量池中。jdk7及以后,由于字符串常量池在堆上,所以intern方法会把第一次遇到的字符串的引用(存放在堆中的引用)放入字符串常量池。若字符串常量池中已经有该字符串就会返回常量池中的该字符串。

package org.example.method;

public class StringIntern {
    public static void main(String[] args) {
        //创建一个存放在堆中的对象
        String s1=new StringBuilder().append("think").append("123").toString();
        //s1.intern获取到的是字符串常量池中存放的对堆中的引用,所以为ture
        System.out.println(s1.intern()==s1);

        // 创建一个存放与于堆上的对象
        String s2=new StringBuilder().append("ja").append("va").toString();
        //由于在启动时就会在字符串常量池中放入“Java”
        //所以s2.intern获取到的是字符串常量池中存放的Java
        System.out.println(s2.intern()==s2);


    }
}

结果是s1的为true,s2的为false 。s1是因为字符串常量池中没有字符串“think123”,所以inturn方法返回的是对堆中该字符串对象的引用,也就是引用的堆中的s1对象。s2是因为程序启动时会自动的在字符串常量池中存放字符串“Java”,所以s2.inturn返回的是字符串常量池中的字符串,而s2是堆中的字符串对象。

直接内存:

  直接内存并不在《JAVA虚拟机规范》中,所以不属于JAVA运行时的内存区域。在jdk1.4中引入了NIO机制,使用了直接内存,只要解决俩个问题:

 1、JAVA堆中的对象如果不再使用要回收,回收时会影响对象的创建和使用。

 2、IO操作,比如读取文件,需要先把文件直接读入直接内存(缓冲区)在把数据复制到JAVA堆中。现在直接放入直接内存即可,同时在JAVA堆中维护直接内存的引用,减少了数据复制的开销。直接内存的空间有上限,会发生内存溢出。如果需要手动调整直接内存的大小,可以使用        -XX:MaxDirectMemorySize=值   单位k或K表示千字节,m或M表示兆字节,g或G表示千兆字节。默认不设置该参数时,jvm自动选择最大分配的大小。

元空间(也就是方法区)使用本机直接内存,不再位于java虚拟机内存中,不受堆的大小限制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/616809.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Electron学习笔记(四)

文章目录 相关笔记笔记说明 六、数据1、使用本地文件持久化数据(1) 用户数据目录(2) 读写本地文件(3) 第三方库 2、读写受限访问的 Cookie3、清空浏览器缓存 相关笔记 Electron学习笔记&#xff08;一&#xff09;Electron学习笔记&#xff08;二&#xff09;Electron学习笔记…

文献阅读——ESG的说与做

The cost of hypocrisy: Does corporate ESG decoupling reduce labor investment efficiency? 主要学习借鉴ESG decoupling 如何构造的&#xff01;&#xff01;&#xff01; 1.引言 在碳峰值和碳中和目标的背景下&#xff0c;尽管上市公司ESG信息披露率不断上升&#xff0c…

【网络基础】网络层 之 IP协议与分片、网段划分、IP地址分类、子网掩码与路由

文章目录 网络层1. IP协议段格式1.1 分片1.2 *为什么存在分片 / 分片是什么 ?*1.3 *如何理解 / 实现 分片与组装*1.4 深入具体&#xff1a;分片 和 组装 的过程1.5 为什么不推荐 分片 2. 网段划分2.1 举例&#xff1a;国际间通信 && 国家内通信2.2 理解网段划分 3. IP…

数据库系统理论——关系数据库标准语言SQL

文章目录 一、数据定义1、基本表的定义、删除与修改2、索引的建立于删除&#xff08;了解&#xff09; 二、数据查询&#xff08;会其中一种&#xff09;1、单表查询&#xff08;1&#xff09;这里出现重复元组&#xff0c;怎么处理&#xff1f;&#xff1f;&#xff08;2&…

39-5 入侵检测系统(IDS)- 安装配置IDS(第三天安装成功)

官网:Snort Rules and IDS Software Download 参考: (这位大佬分享了安装包下载链接):https://www.cnblogs.com/taoyuanming/p/12722263.html (安装过程参考这位大佬):Snort 安装与配置(CentOS 7)_centos 7 snort-CSDN博客一、安装 IDS(我这里在 CentOS 7 虚拟机中安…

关于一致性,你该知道的事儿(下)

关于一致性&#xff0c;你该知道的事儿&#xff08;下&#xff09; 前言一、并发修改单个对象1.1 原子写操作1.2 显示加锁1.3 原子的TestAndSet1.4 版本号机制 二、 多个相关对象的一致性2.1 最大努力实现2.2 2PC && TCCC2.3.基于可靠消息的一致性方案2.4.Saga事务 三、…

Flink container exit 143 问题排查

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

centos7.9系统安全加固

1、限制用户登陆 vim /etc/hosts.deny&#xff0c;若禁止192.168.0.158对服务器进行ssh的登陆&#xff0c;添加如下内容 sshd : 192.168.0.158 添加完毕后就生效了&#xff0c;直接用192.168.0.158访问主机&#xff0c;就无法连接了&#xff0c;显示 Connection closing...Soc…

【密评】 | 商用密码应用安全性评估从业人员考核题库(9/58)

Hill密码是重要古典密码之一&#xff0c;其加密的核心思想的是&#xff08;&#xff09;。 A.线性变换 B.非线性变换 C.循环移位 D.移位 著名的Kerckhoff原则是指&#xff08;&#xff09;。 A.系统的保密性不但依赖于对加密体制或算法的保密&#xff0c;而且依赖于密钥 B.系统…

【JUC】并发编程 Synchronized 锁升级原理

Synchronized如何实现同步/互斥的效果&#xff1f; monitorenter&#xff1a; 将锁对象对象头中Mark Word的前30bit替换成指向操作系统中与其关联的monitor对象&#xff0c;将锁记录位状态改为10 monitorexit&#xff1a; 将锁对象对象头中Mark Word进行重置&#xff0c;重新恢…

Open CASCADE 教程 – AIS:自定义呈现

文章目录 开始 (Getting Started)呈现构建器 (Presentation builders)基元数组 (Primitive arrays)基元外观 (Primitive aspects)二次构建器 (Quadric builders)计算选择 (Computing selection)突出显示选择所有者 (Highlighting selection owner)突出显示的方法 (Highlighting…

【网站项目】SpringBoot796水产养殖系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

vi\vim编辑器

root用户&#xff08;超级管理员&#xff09; 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 在Linux系统中&#xff0c;拥有最大权限的账户名为&#xff1a;root&#xff08;超级管理员&#xff09; root用户拥有最大的系统操作权限&#xff0c;而普通…

改进YOLOv5,YOLOv5+CBAM注意力机制

目录 1. 目标检测模型 2. YOLOv5s 3. YOLOv5s融合注意力机制 4. 修改yolov5.yaml文件 5. ChannelAttentionModule.py 6. 修改yolo.py 1. 目标检测模型 目标检测算法现在已经在实际中广泛应用&#xff0c;其目的是找出图像中感兴趣的对象&#xff0c;并确定对象的类别和位…

牛客NC343 和大于等于K的最短子数组【困难 前缀和 Java/Go】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/3e1fd3d19fb0479d94652d49c7e1ead1 思路 本答案利用前缀和解答&#xff0c;Java&#xff0c;Go答案通过&#xff0c;但是同样的代码用PHP的话有一个测试用例超时 应该还有更优秀的答案&#xff0c;后面找到更优…

如何远程操作服务器中的Python编译器并将运行结果返回到Pycharm

文章目录 一、前期准备1. 检查IDE版本是否支持2. 服务器需要开通SSH服务 二、Pycharm本地链接服务器测试1. 配置服务器python解释器 三、使用内网穿透实现异地链接服务器开发1. 服务器安装Cpolar2. 创建远程连接公网地址 四、使用固定TCP地址远程开发 本文主要介绍如何使用Pych…

分布式与一致性协议之PBFT算法(一)

PBFT算法 概述 前面提到了拜占庭将军问题之后&#xff0c;有人可能会感到困惑:口信消息型拜占庭问题直接在实际项目中是如何落地的呢&#xff1f;事实上&#xff0c;它很难在实际项目中落地&#xff0c;因为口信消息型拜占庭问题之解是一个非常理论化的算法&#xff0c;没有与…

C++类的概念以及用法

目录 面向过程和面向对象初步认识类的引入类的定义类的两种定义方式声明和定义全部放在类体中 声名定义分离 类的作用域成员变量命名规则建议访问限定符 类的封装类的实例化类对象模型类的对象大小的计算扩展 结构体内存对齐规则 感谢各位大佬对我的支持,如果我的文章对你有用,…

《Fundamentals of Power Electronics》——转换器的传递函数

转换器的工程设计过程主要由以下几个主要步骤组成&#xff1a; 1. 定义了规范和其他设计目标。 2. 提出了一种电路。这是一个创造性的过程&#xff0c;利用了工程师的物理洞察力和经验。 3. 对电路进行了建模。组件和系统的其他部分适当建模&#xff0c;通常使用供应商提供的…

祝天下母亲节快乐!虚无!——早读(逆天打工人爬取热门微信文章解读)

练功加精力哦 引言Python 代码第一篇 人民日报【夜读】人与人之间最好的关系&#xff1a;遇事靠谱&#xff0c;懂得感恩第二篇 冯站长之家 三分钟新闻早餐结尾 感恩与善行 是人生旅途中的灯塔 怀感恩之心 行小善之事 它们将指引我们走向光明 引言 今天是母亲节 祝天下的所有母…