JVM堆 栈 方法区详解
一、栈
每当启用一个线程时,JVM就为他分配一个JAVA栈,栈是以帧为单位保存当前线程的运行状态
栈是由栈帧组成,每当线程调用一个java方法时,JVM就会在该线程对应的栈中压入一个帧
只有在调用一个方法时,才为当前栈分配一个帧,然后将该帧压入栈
栈帧帧是由局部变量区、操作数栈和帧数据区组成
java栈上的所有数据都是私有的,任何线程都不能访问另一个线程的栈数据
局部变量区 调用方法时,类型信息确定此方法局部变量区和操作数栈的大小
局部变量区被组织为以一个字长为单位、从0开始计数的数组,类型为short、byte和char的值在存入数组前要被转换成int值,而long和double在数组中占据连续的两项,在访问局部变量中的long或double时,只需取出连续两项的第一项的索引值即可,如某个long值在局部变量区中占据的索引时3、4项,取值时,指令只需取索引为3的long值即可
runInstanceMethod的局部变量区第一项是个reference(引用),它指定的就是对象本身的引用,也就是我们常用的this
但是在runClassMethod方法中,没这个引用,那是因为runClassMethod是个静态方法。
操作数栈 可把操作数栈理解为存储计算时,临时数据的存储区域。
和局部变量区一样,操作数栈也被组织成一个以字长为单位的数组。
但和前者不同的是,它不是通过索引来访问的,而是通过入栈和出栈来访问的。
int a = 100;
int b = 98;
int c = a + b;
帧数据区 java栈帧通过帧数据区存的数据来支持常量池解析、正常方法返回以及异常派发机制
当JVM执行到需要常量池数据的指令时,它都会通过帧数据区中指向常量池的指针来访问它。
处理java方法的正常结束和异常终止:如果是通过return正常结束,则当前栈帧从Java栈中弹出,恢复发起调用的方法的栈。如果方法有返回值,JVM会把返回值压入到发起调用方法的操作数栈。
为了处理java方法中的异常情况,帧数据区还必须保存一个对此方法异常引用表的引用。当异常抛出时,JVM给catch块中的代码。如果没发现,方法立即终止,然后JVM用帧区数据的信息恢复发起调用的方法的帧。然后再发起调用方法的上下文重新抛出同样的异常。
1.Java中的基本数据类型不一定存储在栈中,如果该变量是基本数据类型则存储在栈中,
该变量是一个对象(如:int[] array=new int[]{1,2};
),则在堆中。
2.为什么函数调用要用栈实现?
函数调用的局部状态之所以用栈来记录是因为这些数据的存活时间满足“后入先出”(LIFO)顺序,而栈的基本操作正好就是支持这种顺序的访问
二、堆
(不再造轮子,出门左转 JVM入门——JVM内存结构)
三、方法区
用于存储虚拟机加载的:静态变量+常量+类信息+运行时常量池
类信息:类的版本、字段、方法、接口、构造函数等描述信息
运行时常量池用于存储 Java 类文件常量池中的符号信息
运行时常量池中保存着一些 class 文件中描述的符号引用,同时还会将这些符号引用所翻译出来的直接引用存储在运行时常量池中
HotSpot 方法区变迁
在 JDK1.2 ~ JDK6 的实现中,HotSpot 使用永久代实现方法区
JDK7+ 移除永久代 字符串常量和类引用被移动到 Java Heap中
Oracle 同时收购了 BEA 和 Sun 公司,同时拥有 JRockit 和 HotSpot,在将 JRockit 许多优秀特性移植到 HotSpot 时由于 GC 分代技术遇到了种种困难,所以从 JDK7 开始 Oracle HotSpot 开始移除永久代
影响示例:
1.
- public class Test2 {
- public static void main(String[] args) {
- /**
- * 首先设置 持久代最大和最小内存占用(限定为10M)
- * VM args: -XX:PermSize=10M -XX:MaxPremSize=10M
- */
- List<String> list = new ArrayList<String>();
- // 无限循环 使用 list 对其引用保证 不被GC intern 方法保证其加入到常量池中
- int i = 0;
- while (true) {
- // 此处永久执行,最多就是将整个 int 范围转化成字符串并放入常量池
- list.add(String.valueOf(i++).intern());
- }
- }
- }
将整个 int 范围转化成字符串并放入常量池
JDK1.6常量池在方法区(永久带),设置了最大内存为10M,导致Perm 内存溢出
JDK1.7及以后常量池在堆中,代码执行不会有问题
2.
- public class Test1 {
- public static void main(String[] args) {
- String s1 = new StringBuilder("漠").append("然").toString();
- System.out.println(s1.intern() == s1);
- String s2 = new StringBuilder("漠").append("然").toString();
- System.out.println(s2.intern() == s2);
- }
- }
JDK6 下执行结果为 false、false
在 JDK7 以上执行结果为 true、false
1.在 Java 中直接使用双引号展示的字符串将会在常量池中直接创建
2.String的intern方法首先将尝试在常量池中查找该对象,如果找到则直接返回该对象在常量池中的地址;找不到则将该对象放入常量池后再返回其地址
3. s1--对象堆中的地址
s1.intern()--对象常量池中的引用(JDK1.6方法区 JDK1.7堆)
==>JDK1.6 false JDK1.7 true
4.JDK1.7 s2.intern() == s2 false原因:
s2--新对象s2堆中的地址
s2.intern()--首先尝试在常量池中查找该对象,找到s1(s1.intern()已经将该对象放入常量池),返回s1的地址
参考资料
JVM堆 栈 方法区详解的更多相关文章
- Java 底层机制(JVM/堆/栈/方法区/GC/类加载)
转载:https://www.jianshu.com/p/ae97b692614e?from=timeline JVM体系结构 JVM是一种解释执行class文件的规范技术. JVM体系结构 我翻 ...
- JVM 运行时数据区详解
一.运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同数据区域. 1.有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,所有的线程共享这些数据区. 2.第二种则 ...
- 7.JVM调优-方法区,堆,栈调优详解
通常我们都知道在堆空间新生代Eden区满了,会触发minor GC, 在老年代满了会触发full GC, 触发full GC会导致Stop The World, 那你们知道还有一个区域满了一会触发Fu ...
- Java:Java的堆区、栈区和方法区详解
Java内存空间理解 堆:堆主要存放Java在运行过程中new出来的对象,凡是通过new生成的对象都存放在堆中,对于堆中的对象生命周期的管理由Java虚拟机的垃圾回收机制GC进行回收和统一管理.类的非 ...
- java 堆 栈 方法区的简单分析
Java里的堆(heap)栈(stack)和方法区(method) 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收. 引用数据类型,需要用new来创 ...
- JVM中栈的frames详解
目录 简介 JVM中的栈 Frame Local Variables本地变量 Operand Stacks Dynamic Linking动态链接 方法执行完毕 简介 我们知道JVM运行时数据区域专门 ...
- [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义
前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机, ...
- JVM之栈、堆、方法区(三)
一.CPU和内存的交互 今天除夕,祝大家新年快乐,其实,我们知道的,我们的CPU跟内存会有非常频繁的交互,因为如果这个频繁的交互是交给我们的磁盘的话,那么随着我们的CPU运转速度越来越快,那么我们的磁 ...
- [转载]JAVA内存分析——栈、堆、方法区 程序执行变化过程
面向对象的内存分析 参考:http://www.sxt.cn/Java_jQuery_in_action/object-oriented.html :尚学堂JAVA300集-064内存分析详解_栈_堆 ...
随机推荐
- ie8下input文字偏上select文字偏下
1.ie8下input文字偏上 正常情况下input的显示情况如下 当设置input的高度时,就会出现文字不垂直居中偏上的情况,如图 解决方案 强input的行高line-height与其高度设置一致 ...
- mysql中的单引号/小数点/字符转换为数字/警告信息
我们准备玩点有趣的: select 一个数字: mysql from mysql.user; +---+ | +---+ | | | +---+ rows in set (0.00 sec) mysq ...
- 第一章:获取服务器服务banner
#!c:\\perl\\bin\\perl.exe #读取服务器的首行(banner) use IO::Socket; my $service = '121.201.67.177:ssh'; my $ ...
- U-Boot启动过程完全分析<转>
转载自:http://www.cnblogs.com/heaad/archive/2010/07/17/1779829.html 1.1 U-Boot工作过程 U-Boot启动内核的过程可 ...
- 64_d2
dtc-1.4.4-2.fc26.x86_64.rpm 20-Jun-2017 11:04 89890 dtdinst-20131210-7.fc26.noarch.rpm 11-Feb-2017 0 ...
- c++设计模式系列----factory模式
问题: 假设我们要开发一个游戏--打怪物,首先,游戏有分等级,假设有初级,中级两个个等级(就不用flappy bird模式了,那个比较特殊,对一个玩家来说是难以具有持久吸引力的!),不同的等级怪物也是 ...
- jQuery Mobile + HTML5 获取地理位置信息
这个代码也非常简单,核心是HTML5中GeoLocation API,函数原型定义如下: void getCurrentPosition(in PositionCallback successCa ...
- Guava Cache 使用笔记
https://www.cnblogs.com/parryyang/p/5777019.html https://www.cnblogs.com/shoren/p/guava_cache.html J ...
- window 下 nginx+php+fastcgi 架设备忘
1.配置Php.ini 1)extension_dir = "./ext" 修改这个路径为真实的php的ext路径 2);extension=php_mysql.dll ;exte ...
- Bootstrap新版里的a标签点击后出现下划线解决办法
其实我从失去焦点后发现了下划线消失了就应该知道 Bootstrap对a标签进行了 focus焦点事件. 所以解决办法就是一句:a:focus{text-decoration: none}. 一个笑笑的 ...