02-JVM内存结构

一、JVM内存结构

为了让程序运行起来,虚拟机如何分配内存?

1.1 程序计数器

该内存是给 线程 使用的:每个线程有独立的计数器,其作用是记录下一条jvm的指令地址;是内存区中唯一不存在内存溢出问题的。如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地方法,这个计数器值应为空。

1.2 虚拟机栈

该内存是给 线程 使用的,其作用是让线程独立运行。栈是一个动态的存储区域。
每个线程运行的方法由:局部变量参数返回值类型组成。这些组成部分在被以栈帧的形式封装并压入栈中;每个线程运行只有一个活动栈帧,即只有一个方法正在运行。

  • 局部变量表:是一组变量的存储空间。用于存放方法参数和方法内部定义的局部变量。在class文件的方法的code属性确定其分配的变量表的最大容量;容量以容量槽(slot)为最小单位,且可以复用。jvm规范推荐的容量槽大小为32位。jvm是通过局部变量表的的索引定位的,索引值从0-max。0的位置默认是用于传递方法所属对象实例的引用,在方法中可以使用"this"进行访问这个隐含的参数值。

  • 操作数栈:当一个方法刚刚开始执行时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取数据,就是出栈和入栈操作。java虚拟机的解释执行引擎被称为“基于 栈的执行引擎”,栈即操作数栈。

  • 动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中动态连接。字节码文件中的常量池中有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数。这些符号引用一部分在类加载阶段或者第一次使用的时候转换为直接引用,这种转化被称为静态解析(这部符号符合Java语言“编译期可知,运行期不可变”要求的方法有静态方法、私有方法、构造方法、父类方法和final修饰的方法)。另外一部分将在每一次运行期间都转化为直接引用,这部分称为动态连接(动态调用的形式是分派:静态单(多)分派-重载、动态单(多)分派-重写)。

-Xss1024k:设置线程栈占用内存大小。默认值:不同的操作系统平台,其默认值不同,具体看官网说明。

2.3 本地方法栈

调用由C/C++实现的方法。

2.4 堆

堆主要存储的内容:静态变量(JDK 1.8前放在方法区,JDK 1.8后存放在堆中反射的class对象中)、对象、数组。线程共享区域,存在线程安全问题。

栈属于线程方法执行的区域,所以栈就像客栈一样,属于临时区域,对象占用的内存空间随着出栈而释放;而堆相对于栈,一旦被new创建出来,对象的销毁需要垃圾回收机制的介入。

jdk 1.7的堆逻辑划分
jdk 1.8的堆逻辑划分

堆内存的诊断工具:

  • jps: 查看当前系统有哪些java进程。 在linux中ps是查看进程的。
  • jstat:虚拟机统计信息监视工具。
  • jinfo:java配置信息工具,实时查看和调整虚拟机各项参数。
  • jmap:内存映像工具,生成堆转储快照文件。还可以查询finalize执行队列、java堆和方法区的详细信息。
  • jhat:虚拟机堆转储快照分析工具。
  • jstack:java堆栈跟踪工具,jdk5后Thread.getAllStackTraces()可以实现其大部分功能。
  • jconsole:图形化的内存检测工具。
  • jvisualvm:可视化的虚拟机工具。
  • JHSDB:基于服务性代理的调试工具。

堆的常用设置:

-XX:+PrintFlagsInitial :查看所有的参数默认初始值
-XX:+PrintFlagsFinal :查看左右参数的的最终值,修改后的值
-Xms:初始化堆空间内存(默认为物理内存的1/64)
-Xmx:最大堆空间内存(默认为物理内存的1/4)(建议最大最小值一致,较少系统动态调整空间二浪费性能)
-Xmn:设置新生代的大小。(初始值及最大值)
-XX:NewRatio:配置新生代与老年代在堆结构中的占比默认1:2
-XX:SurvivorRatio:设置神等待中Eden和S0/S1空间的比例(默认为8,但是默认开启动态调整,所有看空间比例可能不是8)
-XX:MaxTenuringThreshold:设置新生代垃圾的最大年龄(默认/最大值为15,超出后转移到老年代)
-XX:+PrintGCDetails:输出详细的GC处理日志
-XX:PrintGc 或 -verbose:gc :打印GC简要信息
-XX:HandlePromotionFailure:是否设置空间分配担保(JDK1.7之后失效,认为是true)

2.5 方法区

虚拟机规范建议:方法区逻辑上应是 的组成部分,在虚拟机启动时候创建。

方法区在逻辑上属于堆,所以Java 虚拟机在一开始的时候,为了重复使用垃圾回收的代码,在堆中使用“永久代”来实现方法区。但是方法区中存放的数据很多容易造成内存溢出,所以在jdk8后将方法区的大部分(除了“串池”)实现放入元数据中。

方法区的规范实现方式不同:

  • jdk6是通过永久代实现:方法区还在jvm的内存中。
  • jdk8是通过元空间实现:方法区大部分数据已经不在jvm的内存中 。
方法区的规范实现方式不同:图中的常量池应为运行时常量池

运行时常量池:当类被加载,常量池(就是一张表,虚拟机指令根据这张表找到要执行的类名、方法名、参数类型和字面量。是存储在字节码文件中)中的数据就会放入内存中的运行时常量池,并把里面的符号地址变为真实地址。

StringTable:是运行时常量池的重要组成部分,是哈希表结构,是存放运行时字符串包括类名、方法名等。 jdk8时候已经从元空间抽离到堆内存中。

s3是存放在StringTable内存中的;而s4是存放在堆内存中;s4在编译期间不能优化
javac编译期间优化后:s3等同于s5,所以s3==s5

在1.8 中intern将某个字符串放入StringTable中时,如果StringTable中没有对应的字符串,则会把该字符串放入StringTable,并把StringTable中的对象返回。

在1.6 中intern将某个字符串放入StringTable中时,如果StringTable中没有对应的字符串,则会把该字符串复制一份放入StringTable,并把StringTable中的对象返回。

1.8 使用intern可以将StringTable没有的字符串放入StringTable:放入成功
1.8 使用intern可以将StringTable没有的字符串放入StringTable:放入失败

当操作大量重复字符串的时候,考虑使用intern将字符串放入“串池”中,由于“串池”是哈希表结构,所以会自动去重,可以有效降低内存的占用。

2.6 OS系统内存

不受JVM的垃圾回收管理(是由JVM的Unsafe对象管理的),常见于NIO操作时,数据缓冲区,分配和回收成本高,但读写效率高。
内存溢出会抛出Direct Buffer Memory

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容

  • Java虚拟机在执行java程序的过程中会把它所管理的内存化分为若干个不同的数据区域。这些区域有各自的用途,以及创...
    lilykeke阅读 148评论 0 0
  • jvm内存结构 1.程序计数器 1.1 定义 Program Counter Register 程序计数器(寄存器...
    韩who阅读 388评论 0 0
  • 一、什么是JVM 定义 Java Virtual Machine,JAVA程序的运行环境(JAVA二进制字节码的运...
    zhemehao819阅读 178评论 0 0
  • java语言作为高级语言,最主依赖之一就算是内存的自动分配和回收的功能了。不像c语言那样,需要程序员自己去主动的,...
    联想桥南阅读 277评论 0 2
  • java的内存结构(一) 大佬都讲的巨详细了,深度干货啊,没啥要补充的了http://www.cnblogs.co...
    黄靠谱阅读 1,221评论 0 0