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的地址
参考资料
1.深入JVM——栈和局部变量
2.Java堆和栈看这篇就够了
3.JVM入门——JVM内存结构
4.Java 内存之方法区和运行时常量池
转载于:https://www.cnblogs.com/hexinwei1/p/9414018.html
JVM堆 栈 方法区详解相关推荐
- 欧尼酱讲JVM(17)——方法区详解有图有真相
目录 位置图解 方法区的理解 方法区在哪里 方法区的基本理解 HotSpot中方法区的理解(演进过程) 方法区的内部结构 图解方法区内部结构 运行时常量池 class文件中常量池的理解 为什么需要常量 ...
- JVM - 结合代码示例彻底搞懂Java内存区域_对象在堆-栈-方法区(元空间)之间的关系
文章目录 Pre 示例demo 总体关系 代码示例论证 反汇编 Pre JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器 中我们探讨了线程栈中的内部结构 ,大家 ...
- JVM Runtime Data Area(运行时数据区中的堆/栈/方法区讲解)
JVM的组成 JVM由4大部分组成:ClassLoader .Runtime Data Area .Execution Engine .Native Interface.我们这里重点讲得是Runtim ...
- JVM 运行时数据区详解,写得非常好!
作者:小小木的博客 www.cnblogs.com/wyc1994666/p/11795781.html 在接下来的几天想总结下,JVM相关的一些内容,比如下面的这三个内容算是比较核心知识点了 1.运 ...
- java 线程栈大小配置,JVM运行时数据区详解-Stack栈(优化配置、代码样例)
最近有段时间没有更新Netty的教程了,却发了一些其他的东西.可能有的朋友会问,难道这就完事了?不会的.两方面原因.第一.笔者也是需要工作的人,自然要完成好工作中的任务,这里面也有很多东西需要学习和研 ...
- JVM中栈的frames详解
文章目录 简介 JVM中的栈 Frame Local Variables本地变量 Operand Stacks Dynamic Linking动态链接 方法执行完毕 简介 我们知道JVM运行时数据区域 ...
- jvm堆外内存排查详解
文章目录 前言 一.堆外内存排查 1.背景 2.内存对比 3.堆外内存检查 4.排查堆外内存 5.glibc内存泄露 结尾 前言 内存泄漏想必大家并不陌生,对于jvm的内存泄漏,有很多排查手段和方便的 ...
- JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)
JVM(Java虚拟机) JVM 内存模型 结构图 jdk1.8 结构图(极简) jdk1.8 结构图(简单) JVM(Java虚拟机): 是一个抽象的计算模型. 如同一台真实的机器,它有自己的指令集 ...
- 为什么jvm要分为堆、方法区等?原理是什么?_「JVM」知识点详解一:JVM运行原理详解...
前言 JVM 一直都是面试的必考点,大家都知道,但是要把它搞清楚又好像不是特别容易.JVM 的知识点太散,不系统,今天带大家详细的了解一下jvm的运行原理. 正文 1 什么是JVM? JVM是Java ...
最新文章
- Python3 xml模块的增删改查
- 《循序渐进学Spark》一3.5 容错机制及依赖
- OpenStack技术峰会PPT集萃
- java的函数库_Dagli首页、文档和下载 - Java 机器学习函数库
- svn 服务器的搭建以及客户端的使用
- python3 Xml操作
- c语言程序输出时有没有分号,问什么C程序里总是提示缺少分号;,而明明有分号?...
- 南桥芯片组行业调研报告 - 市场现状分析与发展前景预测
- 机器学习算法与Python学习
- java后台开发程序媛~~
- PHP Smarty 学习手册
- 抖音视频如何一键批量下载
- vs2017优雅配色
- oracle配置ipv6_配置 IPv6 路由器
- (JavaScript)Mixin 模式
- 印度的“健康码”:Aarogya Setu为何会失败?
- Windows程序开机自启动
- C#之父Anders Hejlsberg演讲解读:编程语言大趋势
- ucGUI390 触摸消息响应过程
- 本人的博客迁移到多个平台,小伙伴们多多支持……
热门文章
- 匿名黑客Anonymous实施的8次最强攻击
- Ubuntu 16.04 install NVDIA display driver
- bzoj1251: 序列终结者 (splay)
- Android Timer的使用
- Tensorflow源码解析5 -- 图的边 - Tensor
- 激动人心的AutoCAD .net开发技术
- 互联网企业安全高级指南3.7.1 攻防驱动修改
- jquery.ajax的url中传递中文乱码问题的解决方法
- Linux之DNS服务
- How to check Laravel version?