JVM内存模型和结构

JVM内存模型和结构
JVM内存模型和结构:
1.有些区域随虚拟机的启动⽽存在
2.有些区域随线程的启动⽽启动,随线程的结束⽽销毁
JVM运⾏时内存结构
JVM的内存结构⼤概分为:
1.堆(Heap):线程共享。所有的对象实例以及数组都要在堆上分配。回收器主要管理的对象。
2.⽅法区(Method Area):线程共享。存储类信息、常量、静态变量、即时编译器编译后的代码。
3.虚拟机栈(JVM Stack):线程私有。存储局部变量表、操作栈、动态链接、⽅法出⼝,对象指针。
4.本地⽅法栈(Native Method Stack):线程私有。为虚拟机使⽤到的Native ⽅法服务。如Java使⽤c或者c++编写的接⼝服务时,代码在此区运⾏。
5.程序计数器(Program Counter Register):线程私有。有些⽂章也翻译成PC寄存器(PC Register),同⼀个东西。它可以看作是当前线程所执⾏的字节码的⾏号指⽰器。指向下⼀条要执⾏的指令。
堆的作⽤是存放对象实例和数组。从结构上来分,可以分为新⽣代和⽼年代。⽽新⽣代⼜可以分为Eden 空间、From Survivor 空间
(s0)、To Survivor 空间(s1)。 所有新⽣成的对象⾸先都是放在新⽣代的。需要注意,Survivor的两个区是对称的,没先后关系,所以同⼀个区中可能同时存在从Eden复制过来的对象,和从前⼀个Survivor复制过来的对象,⽽复制到⽼年代的只有从第⼀个Survivor区过来的对象。⽽且,Survivor区总有⼀个是空的。
控制参数
-Xms设置堆的最⼩空间⼤⼩。-Xmx设置堆的最⼤空间⼤⼩。-XX:NewSize设置新⽣代最⼩空间⼤⼩。-XX:MaxNewSize设置新⽣代最⼩空间⼤⼩。
垃圾回收
此区域是垃圾回收的主要操作区域。
异常情况
如果在堆中没有内存完成实例分配,并且堆也⽆法再扩展时,将会抛出OutOfMemoryError 异常
⽅法区
成都理工大学学报
⽅法区(Method Area)与Java 堆⼀样,是各个线程共享的内存区域,它⽤于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java 虚拟机规范把⽅法区描述为堆的⼀个逻辑部分,但是它却有⼀个别名叫做Non-Heap(⾮堆),⽬的应该是与Java 堆区分开来。
很多⼈愿意把⽅法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC 分代收集扩展⾄⽅法区,或者说使⽤永久代来实现⽅法区⽽已。对于其他虚拟机(如BEA JRockit、IBM J9 等)来说是不存在永久代的概念的。在Java8中永⽣代彻底消失了。
控制参数
-XX:PermSize 设置最⼩空间 -XX:MaxPermSize 设置最⼤空间。
垃圾回收
共沸精馏对此区域会涉及但是很少进⾏垃圾回收。这个区域的内存回收⽬标主要是针对常量池的回收和对类型的卸载,⼀般来说这个区域的回收“成绩”⽐较难以令⼈满意。
异常情况
根据Java 虚拟机规范的规定, 当⽅法区⽆法满⾜内存分配需求时,将抛出OutOfMemoryError。
⽅法栈
每个线程会有⼀个私有的栈。每个线程中⽅法的调⽤⼜会在本栈中创建⼀个栈帧。在⽅法栈中会存放编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引⽤(reference 类型,它不等同于对象本⾝。局部变量表所需的内存空间在编译期间完成分配,当进⼊⼀个⽅法时,这个⽅法需要在帧中分配多⼤的局部变量空间是完全确定的,在⽅法运⾏期间不会改变局部变量表的⼤⼩。
控制参数
-Xss控制每个线程栈的⼤⼩。十六大领导班子
异常情况
在Java 虚拟机规范中,对这个区域规定了两种异常状况:
StackOverflowError: 异常线程请求的栈深度⼤于虚拟机所允许的深度时抛出;
OutOfMemoryError 异常: 虚拟机栈可以动态扩展,当扩展时⽆法申请到⾜够的内存时会抛出。
本地⽅法栈
本地⽅法栈(Native Method Stacks)与虚拟机栈所发挥的作⽤是⾮常相似的,其
区别不过是虚拟机栈为虚拟机执⾏Java ⽅法(也就是字节码)服务,⽽本地⽅法栈则
是为虚拟机使⽤到的Native ⽅法服务。
控制参数
在Sun JDK中本地⽅法栈和⽅法栈是同⼀个,因此也可以⽤-Xss控制每个线程的⼤⼩。
异常情况
与虚拟机栈⼀样,本地⽅法栈区域也会抛出StackOverflowError 和OutOfMemoryError异常。
程序计数器
它的作⽤可以看做是当前线程所执⾏的字节码的⾏号指⽰器。
异常情况
此内存区域是唯⼀⼀个在Java 虚拟机规范中没有规定任何OutOfMemoryError 情况的区域。
常见内存溢出错误
有了对内存结构清晰的认识,就可以帮助我们理解不同的OutOfMemoryErrors,下⾯列举⼀些⽐较常见的内存溢出错误,通过查看冒
号“:”后⾯的提⽰信息,基本上就能断定是JVM运⾏时数据的哪个区域出现了问题。
Exception in thread “main”: java.lang.OutOfMemoryError: Java heap space
上海集邮
原因:对象不能被分配到堆内存中。
Exception in thread “main”: java.lang.OutOfMemoryError: PermGen space
原因:类或者⽅法不能被加载到⽼年代。它可能出现在⼀个程序加载很多类的时候,⽐如引⽤了很多第三⽅的库。
Exception in thread “main”: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
原因:创建的数组⼤于堆内存的空间。
Exception in thread “main”: java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of
swap space?
原因:分配本地分配失败。JNI、本地库或者Java虚拟机都会从本地堆中分配内存空间。
Exception in thread “main”: java.lang.OutOfMemoryError: <reason> <stack trace>(Native method)
原因:同样是本地⽅法内存分配失败,只不过是JNI或者本地⽅法或者Java虚拟机发现。
1.不同的虚拟机实现可能不同,但是⼀般都会遵守规范
2.规范中⽅法区只是⼀种概念上的区域,说明了其应该具有的功能,但并没有说明其具体应该位于何处。不同的虚拟机实现,会有⼀定的⾃由度。有些虚拟机是在堆内实现的
3.运⾏时常量池⽤于存放编译期的各种字⾯值和符号引⽤。不过Java并没有要求常量只能在编译期才能产⽣,通过String.intern也能产⽣
4.除了图中所列的内存区域,还有⼀块内存可供使⽤,那就是直接内存。JVM规范并没有定义这⼀块区域,所以并不由JVM管理,是利⽤本地⽅法库直接在堆外申请的内存
5.堆和栈的数据划分并不是绝对的,JIT会针对对象分配做⼀定的优化
JVM内存结构由JVM虚拟机规范定义。描述的是java程序执⾏过程中,由JVM管理的不同数据区域,各个区域的功能会有区别
白介素82. Java内存模型
Java堆和⽅法区是多个线程共享的数据区域。多个线程可以操作堆和⽅法区中的同⼀个数据。Java的线程间通过共享内存进⾏通信
1.Java内存模型的英⽂名称为Java Memory Model(JMM),其并不想JVM内存结构⼀样真实存在,⽽是⼀个抽象的概念。通过JSR-
中国知网首页133 Java Memory Model and Thread Specification中的描述,我们知道JMM和线程有关,它描述了⼀组规范或规则,⼀个线程对共享变量的写⼊时对另⼀个线程是可见的。
2.Java多线程对共享内存进⾏操作的时候,会存在⼀些如可见性、原⼦性和顺序性的问题,JMM是围绕着多线程通信及相关的⼀些特
性⽽建⽴的模型。⽽JMM定义了⼀些语法集,⽽这些语法集映射到Java语⾔的volatile、synchronized等关键字
3. Java对象模型
Java对象在JVM中的存储有⼀定的结构,Java对象⾃⾝的存储模型就叫做Java对象模型。
总:
JVM内存结构,和Java虚拟机的运⾏时区域有关。 Java内存模型,和Java的并发编程有关。 Java对象模型,和Java对象在虚拟机中的表现形式有关。

本文发布于:2024-09-22 15:38:12,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/335559.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:内存   区域   线程   对象   分配   编译   回收   规范
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议