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获取到的是字符串常量池中存放的对堆中的引用,所以为tureSystem.out.println(s1.intern()==s1);// 创建一个存放与于堆上的对象String s2=new StringBuilder().append("ja").append("va").toString();//由于在启动时就会在字符串常量池中放入“Java”//所以s2.intern获取到的是字符串常量池中存放的JavaSystem.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虚拟机内存中,不受堆的大小限制。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51基于单片机的温室大棚系统设计

设计摘要&#xff1a; 本设计旨在基于51单片机和蓝牙技术&#xff0c;实现一个功能完善的温室大棚系统。该系统具备以下主要功能&#xff1a;首先&#xff0c;通过连接的显示屏能够实时地显示当前的温度和湿度信息&#xff0c;方便用户了解温室内的环境变化。其次&#xff0c;…

Neo4j 之安装和 CQL 基本命令学习

正常使用结构化的查询语言 SQL&#xff08;Structured Query Language&#xff09;较多一些&#xff0c;但是像 Neo4j 这种非结构化的图形数据库来说&#xff0c;就不得不学习下 CQL&#xff08;Cypher Query Language&#xff09;语言了。如果你之前学过 《离散数学》或《图论…

使用SPI驱动串行LCD的驱动实现(STM32F4)

目录 概述 1. 硬件介绍 1.1 ST7796-LCD 1.2 MCU IO与LCD PIN对应关系 2 功能实现 2.1 使用STM32Cube配置Project 2.2 STM32Cube生成工程 3 代码实现 3.1 SPI接口实现 3.2 LCD驱动程序实现 3.3 测试程序实现 4 测试 源代码下载地址&#xff1a; https://gitee.com/mf…

常用Linux命令详细总结

一、文档编辑、过滤、查看命令 1、cp 复制文件和目录 -a 复制文件并保持文件属性 -d 若源文件为链接文件&#xff0c;则复制链接文件属性而非文件本身 -i 覆盖文件前提示&#xff0c;如果不要提示&#xff0c;在命令前加上\ -r 递归复制&#xff0c;通常用于目录的复制 …

C++的数据结构(三):栈

栈&#xff08;Stack&#xff09;是一种后进先出&#xff08;LIFO, Last In First Out&#xff09;的数据结构&#xff0c;它只允许在一端&#xff08;称为栈顶&#xff09;进行插入和删除操作。栈的这种特性使得它在解决函数调用、括号匹配、表达式求值等问题时具有天然的优势…

SpringCloud 2023.0.1

本文介绍如何使用 springboot3及cloud2023 进行微服务模块化开发 采用父-module 模块开发 父工程 demo-java pom.xml <!--配置 springboot的依赖的版本号, 方便 module 进行继承--><dependencyManagement><dependencies><!--增加 springboot的依赖--&g…

宝塔安装多个版本的PHP,如何设置默认的PHP版本

如何将默认的PHP版本设置为7.3.32&#xff0c; 创建软链接指向7.3版本&#xff0c;关键命令&#xff1a;ln -sf /www/server/php/73/bin/php /usr/bin/php 然后再查看PHP版本验证一下结果 [rootlocalhost ~]# ln -sf /www/server/php/73/bin/php /usr/bin/php [rootlocalho…

zabbix“专家坐诊”第238期问答

问题一 Q&#xff1a;请问一下 zabbix 如何监控服务器端口的出和入流量?就类似iftop这样的。 A&#xff1a;可以用snmp去监控。 问题二 Q&#xff1a;各位有什么工具能导出zabbix主机列表成execl格式吗&#xff1f; A&#xff1a;进mysql&#xff0c;到hostid&#xff0c;然…

WEB后端复习——监听器、过滤器

Listener监听器 是Servlet规范中定义的一种特殊类&#xff0c;它用于监听web应用程序中的ServletContext, HttpSession和ServletRequest等域对象的创建与销毁事件&#xff0c;以及监听这些域对象中的属性发生修改的事件。 注解WebListener 1.ServletContextListener 监听Serv…

Python3 + Appium + 安卓模拟器实现APP自动化测试并生成测试报告

这篇文章主要介绍了Python3 Appium 安卓模拟器实现APP自动化测试并生成测试报告,本文给大家介绍的非常详细&#xff0c;对大家的学习或工作具有一定的参考借鉴价值&#xff0c;需要的朋友可以参考下 本文主要分为以下几个部分 安装Python3 安装Python3的Appium库 安装Andr…

K-CU12和利时工控单元

K-CU12和利时工控单元。控制策略组态&#xff0c;使用专用的组态软件 人机界面HMI设计&#xff1a;操作员站画面设计&#xff0c;使用专用的组态软件 K-CU12和利时工控单元文件组态 2文档管理软件 在工程师站上进行系统组态的主要工作&#xff1a; K-CU12和利时工控单元。系统配…

【全开源】Fastflow工作流系统(源码搭建/上线/运营/售后/维护更新)

一款基于FastAdminThinkPHP开发的可视化工作流程审批插件&#xff0c;帮助用户基于企业业务模式和管理模式自行定义所需的各种流程应用&#xff0c;快速构建企业自身的流程管控体系&#xff0c;快速融合至企业协同OA办公系统。 提供全部无加密服务端源码和前端源代码&#xff0…

如何在 Linux / Ubuntu 上下载和安装 JMeter?

Apache JMeter 是一个开源的负载测试工具&#xff0c;可以用于测试静态和动态资源&#xff0c;确定服务器的性能和稳定性。在本文中&#xff0c;我们将讨论如何下载和安装 JMeter。 安装 Java&#xff08;已安装 Java 的此步骤可跳过&#xff09; 安装 Java 要下载 Java&…

【计算机网络篇】数据链路层(10)在物理层扩展以太网

文章目录 &#x1f354;扩展站点与集线器之间的距离&#x1f6f8;扩展共享式以太网的覆盖范围和站点数量 &#x1f354;扩展站点与集线器之间的距离 &#x1f6f8;扩展共享式以太网的覆盖范围和站点数量 以太网集线器一般具有8~32个接口&#xff0c;如果要连接的站点数量超过了…

使用Three.js绘制快速而逼真的水

本文将利用GPUComputationRenderer来实现水波纹的绘制&#xff0c;相似的案例可以看threejs官方的GPGPU Water示例。更多精彩内容尽在数字孪生平台。 什么是 GPGPU GPGPU代表通用图形处理单元&#xff08;General-Purpose Graphic Processing Unit&#xff09;&#xff0c;意思…

从0开始linux(2)——热键、如何查阅手册

欢迎来到博主的专栏——从0开始linux 博主ID&#xff1a;代码小豪 博主使用的linux发行版&#xff1a;CentOS 7.6 文章目录 热键[Tab]热键Ctrl cshift[pageup]和[pagedown] 查阅手册\-\-help在线手册maninfo手册 热键 我们的命令行模式中存在很多的组合热键&#xff0c;这些按…

神经网络中的算法优化(皮毛讲解)

抛砖引玉 在深度学习中&#xff0c;优化算法是训练神经网络时至关重要的一部分。 优化算法的目标是最小化&#xff08;或最大化&#xff09;一个损失函数&#xff0c;通常通过调整神经网络的参数来实现。 这个过程可以通过梯度下降法来完成&#xff0c;其中梯度指的是损失函数…

利用“AnaTraf“网络流量分析仪轻松诊断和优化网络

网络性能监测和诊断(NPMD)是网络管理和优化的重要环节,准确快速地定位和排除网络故障对于保障业务正常运转至关重要。作为一款专业的网络流量分析设备,AnaTraf网络流量分析仪凭借其强大的流量分析和故障诊断功能,为网络管理者提供了一个高效的网络优化解决方案。 全面掌握网络…

计算机网络实验1:交换机基本配置管理

实验目的和要求 安装Packer Tracer&#xff0c;了解Packer Tracer的基本操作掌握交换机基本命令集实验项目内容 认识Packet Tracer软件 交换机的基本配置与管理 交换机的端口配置与管理 交换机的端口聚合配置 交换机划分Vlan配置 实验环境 硬件&#xff1a;PC机&#x…

体验MouseBoost PRO,让Mac操作更高效

还在为Mac的右键功能而烦恼吗&#xff1f;试试MouseBoost PRO for Mac吧&#xff01;这款强大的鼠标右键增强软件&#xff0c;能让你通过简单操作即可激活多种实用功能&#xff0c;让你的工作变得更加轻松。其高度定制化的设计&#xff0c;更能满足你的个性化需求。赶快下载体验…