html5 图片展示网站建设隔离变压器移动网站
web/
2025/9/28 21:28:03/
文章来源:
html5 图片展示网站,建设隔离变压器移动网站,湖南郴州最新消息,潍坊做网站建设运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域#xff0c;称之为运行时数据区。 《Java虚拟机规范》中规定了每一部分的作用 线程不共享#xff1a;程序计数器、虚拟机栈、本地方法栈 线程共享#xff1a;方法区#xff0c;堆
1. 程序计数器(Program Count… 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域称之为运行时数据区。 《Java虚拟机规范》中规定了每一部分的作用 线程不共享程序计数器、虚拟机栈、本地方法栈 线程共享方法区堆
1. 程序计数器(Program Counter Register)
程序计数器也叫PC寄存器每个线程会通过程序计数器记录当前要执行的的字节码指令的地址。在加载阶段虚拟机将字节码文件中的指令读取到内存之后会将原文件中的偏移量转换成内存地址。每一条字节码指令都会拥有一个内存地址。
在代码执行过程中程序计数器会记录下一行字节码指令的地址。执行完当前指令之后虚拟机的执行引擎根据程序计数器执行下一行指令。
程序计数器可以控制程序指令的进行实现分支、跳转、异常等逻辑。
在多线程执行情况下Java虚拟机需要通过程序计数器记录CPU切换前解释执行到那一句指令并继续解释运行。 程序计数器在运行中会出现内存溢出吗 内存溢出指的是程序在使用某一块内存区域时存放的数据需要占用的内存大小超过了虚拟机能提供的内存上限。 因为每个线程只存储一个固定长度的内存地址程序计数器是不会发生内存溢出的。 程序员无需对程序计数器做任何处理。 2. Java虚拟机栈Java Virtual Machine Stack
Java虚拟机栈Java Virtual Machine Stack采用栈的数据结构来管理方法调用中的基本数据先进后出First In Last Out,每一个方法的调用使用一个栈帧Stack Frame来保存
可以通过idea来查看线程的栈帧情况 Java虚拟机栈随着线程的创建而创建而回收则会在线程的销毁时进行。由于方法可能会在不同线程中执行每个线程都会包含一个自己的虚拟机栈 栈帧组成局部变量表、操作数栈、帧数据
1局部变量表
局部变量表的作用是在方法执行过程中存放所有的局部变量。编译成字节码文件时就可以确定局部变量表的内容。 栈帧中的局部变量表是一个数组数组中每一个位置称之为槽(slot) long和double类型占用两个槽其他类型占用一个槽。 实例方法中的序号为0的位置存放的是this指的是当前调用方法的对象运行时会在内存中存放实例对象的地址。
方法参数也会保存在局部变量表中其顺序与方法中参数定义的顺序一致。
局部变量表保存的内容有实例方法的this对象方法的参数方法体中声明的局部变量。 为了节省空间局部变量表中的槽是可以复用的一旦某个局部变量不再生效当前槽就可以再次被使用。 思考以下代码的局部变量表中会占用几个槽 答局部变量表占用如下图 2操作数栈
栈帧中虚拟机在执行指令过程中用来存放临时数据的一块区域是一种栈式的数据结构如果一条指令将一个值压入操作数栈则后面的指令可以弹出并使用该值。在编译期就可以确定操作数栈的最大深度从而在执行时正确的分配内存大小。 加法运算中操作数栈的应用
3帧数据
主要包含动态链接、方法出口、异常表的引用 动态链接保存了编号到运行时常量池的内存地址的映射关系。当前类的字节码指令引用了其他类的属性或者方法时需要将符号引用编号转换成对应的运行时常量池中的内存地址。 方法出口指的是方法在正确或者异常结束时当前栈帧会被弹出同时程序计数器应该指向上一个栈帧中的下一条指令的地址。所以在当前栈帧中需要存储此方法出口的地址。 异常表存放的是代码中异常的处理信息包含了异常捕获的生效范围以及异常发生后跳转到的字节码指令位置。
栈内存溢出
Java虚拟机栈如果栈帧过多占用内存超过栈内存可以分配的最大大小就会出现内存溢出。虚拟机栈内存溢出时会出现StackOverflowError的错误。 如果我们不指定栈的大小JVM 将创建一个具有默认大小的栈。大小取决于操作系统和计算机的体系结构。要修改Java虚拟机栈的大小可以使用虚拟机参数 -Xss 。字节默认必须是 1024 的倍数、k或者K(KB)、m或者M(MB)、g或者G(GB) 图6 栈内存溢出模拟 使用递归让方法调用自身但是不设置退出条件。定义调用次数的变量每一次调用让变量加1。查看错误发生时总调用的次数。 public static int count 0;//递归方法调用自己public static void recursion(){System.out.println(count);recursion();}要修改Java虚拟机栈的大小可以使用虚拟机参数 -Xss 。 语法-Xss栈大小 单位字节默认必须是 1024 的倍数、k或者K(KB)、m或者M(MB)、g或者G(GB)
注意事项
与-Xss类似也可以使用-XX:ThreadStackSize调整标志来配置堆栈大小。 格式为 -XX:ThreadStackSize1024HotSpot JVM对栈大小的最大值和最小值有要求 比如测试如下两个参数: -Xss1k -Xss1025m Windows64位下的JDK8测试最小值为180k最大值为1024m。局部变量过多、操作数栈深度过大也会影响栈内存的大小。 一般情况下工作中即便使用了递归进行操作栈的深度最多也只能到几百,不会出现栈的溢出。所以此参数可以手动指定为-Xss256k节省内存。 3. 本地方法栈Local Method Stack
Java虚拟机栈存储了Java方法调用时的栈帧而本地方法栈存储的是native本地方法的栈帧。 在Hotspot虚拟机中Java虚拟机栈和本地方法栈实现上使用了同一个栈空间。本地方法栈会在栈内存上生成一个栈帧临时保存方法的参数同时方便出现异常时也把本地方法的栈信息打印出来。 4. 堆Heap
1) Java程序中堆内存是空间最大的一块内存区域。创建出来的对象都存在于堆上
栈上的局部变量表中可以存放堆上对象的引用。静态变量也可以存放堆对象的引用通过静态变量就可以实现对象在线程之间共享。 堆内存大小有上限当一直向堆中放入对象达到上限之后会抛出OutOfMemory错误。
2) 堆空间有三个需要关注的值
used: 指的是当前已使用的堆内存 total: 是java虚拟机已经分配的可用堆内存 max: 是java虚拟机可以分配的最大堆内存
随着堆中的对象增多当total可以使用的内存即将不足时java虚拟机会继续分配内存给堆total值会变大最多只能与max相等。如果不设置任何的虚拟机参数max默认是系统内存的1/4total默认是系统内存的1/64。在实际应用中一般都需要设置total和max的值。 Java服务端程序开发时建议将-Xmx和-Xms设置为相同的值这样在程序启动之后可使用的总内存就是最大内存而无需向java虚拟机再次申请减少了申请并分配内存时间上的开销同时也不会出现内存过剩之后堆收缩的情况。 堆 – 设置大小使用虚拟机参数 –Xmxmax最大值和-Xms (初始的total)。单位字节默认必须是 1024 的倍数、k或者K、m或者M、g或者G. Oracle官方文档https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html 3arthas中堆内存相关的功能
可以通过dashboard命令看到堆内存used、total、max三个值。 手动指定刷新频率默认5秒一次dashboard –i 刷新频率(毫秒) 可使用memory命令只查看内存的信息不会自动刷新 要修改堆的大小可以使用虚拟机参数 –Xmxmax最大值和-Xms (初始的total) 语法-Xmx值 -Xms值 单位字节默认必须是 1024 的倍数、k或者K(KB)、m或者M(MB)、g或者G(GB) 限制Xmx必须大于 2 MBXms必须大于1MB 5. 方法区
方法区是存放基础信息的位置线程共享主要包含三部分内容类的元信息、运行时常量池、字符串常量池
1类的元信息
存储每个类的基本信息一般称之为InstanceKlass对象。在类的加载阶段完成。
2运行时常量池
存放的是字节码中的常量池内容。字节码文件中通过编号查表的方式找到常量这种常量池称为静态常量池。当常量池加载到内存中之后可以通过内存地址快速的定位到常量池中的内容这种常量池称为运行时常量池。 方法区是《Java虚拟机规范》中设计的虚拟概念每款Java虚拟机在实现上都各不相同。Hotspot设计如下 JDK7及之前的版本将方法区存放在堆区域中的永久代空间堆的大小由虚拟机参数来控制。 JDK8及之后的版本将方法区存放在元空间中元空间位于操作系统维护的直接内存中不属于系统给jvm分配的内存默认情况下只要不超过操作系统承受的上限可以一直分配。可以使用“-XX:MaxMetaspaceSize值”将元空间最大大小进行限制 arthas中查看方法区 使用memory打印出内存情况JDK7及之前的版本查看ps_perm_gen属性。 JDK8及之后的版本查看metaspace属性。 JDK7和JDK8在方法区的存放上采用了不同的设计: JDK7将方法区存放在堆区域中的永久代空间堆的大小由虚拟机参数-XX:MaxPermSize值来控制。 JDK8将方法区存放在元空间中元空间位于操作系统维护的直接内存中默认情况下只要不超过操作系统承受的上限可以一直分配。可以使用-XX:MaxMetaspaceSize值将元空间最大大小进行限制。 3字符串常量池
方法区中除了类的元信息、运行时常量池之外还有一块区域叫字符串常量池(StringTable)。 字符串常量池存储在代码中定义的常量字符串内容。比如“123” 这个123就会被放入字符串常量池。
字符串常量池和运行时常量池有什么关系
案例通过字节码指令分析如下代码的运行结果
问题1
public static void main(String[] args){String a 1;String b 2;String c 12;String d ab;System.out.println(cd);
}答案: false 分析: 图6 d是a和b两个变量连接创建了StringBuilder对象生成的a,b,c都是常量池的字符串 问题2
public static void main(String[] args){
String a 1;
String b 2;
String c 12;
String d 1 2;
System.out.println(cd);
}答案: true 分析: 在编译期就直接将1和2拼接为字符串12没有创建对象 问题静态变量存储在哪里 JDK6及之前的版本中静态变量是存放在方法区中的也就是永久代 JDK7及之后的版本中静态变量是存放在堆中的Class对象中脱离了永久代。
6. 直接内存(Direct Memory)
直接内存Direct Memory并不在《Java虚拟机规范》中存在所以并不属于Java运行时的内存区域。
在 JDK 1.4 中引入了 NIO 机制使用了直接内存主要为了解决以下两个问题: 1、Java堆中的对象如果不再使用要回收回收时会影响对象的创建和使用。 2、IO操作比如读文件需要先把文件读入直接内存缓冲区再把数据复制到Java堆中。现在直接放入直接内存即可同时Java堆上维护直接内存的引用减少了数据复制的开销。写文件也是类似的思路。 要创建直接内存上的数据可以使用ByteBuffer。 语法 ByteBuffer directBuffer ByteBuffer.allocateDirect(size); 手动调整直接内存的大小可以使用-XX:MaxDirectMemorySize大小 arthas的memory命令可以查看直接内存大小属性名direct。 如果需要手动调整直接内存的大小可以使用-XX:MaxDirectMemorySize大小 单位k或K表示千字节m或M表示兆字节g或G表示千兆字节。默认不设置该参数情况下JVM 自动选择最大分配的大小。 7. 总结
1) 运行时数据区分成哪几部分每一部分的作用是什么
程序计数器、Java虚拟机栈、本地方法栈、方法区、堆 每个线程会通过程序计数器记录当前要执行的的字节码指令的地址程序计数器可以控制程序指令的进行实现分支、跳转、异常等逻辑。 虚拟机栈采用栈的数据结构来管理方法调用中的基本数据局部变量、操作数等每一个方法的调用使用一个栈帧来保存。 堆中存放的是创建出来的对象这也是最容易产生内存溢出的位置 方法区中主要存放的是类的元信息同时还保存了常量池
2) 不同JDK版本之间运行时数据区域的区别是什么
jdk6 JDK7 JDK8
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/83537.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!