jvm内存结构(一)(结构总览)

jvm内存结构:《Java虚拟机原理图解》3、JVM运行时数据区

程序计数器:

1,是执行的字节码的行号指示器,记录的是正在执行的虚拟机字节码指令的地址。
2,每个线程都有独立计数器,互不干扰。
3,唯一不会发生内存泄漏的一块区域。

Java虚拟机栈:

1,这是我们通常所说的“堆和栈”中存放局部变量的栈(和存放对象的堆),但是却不仅仅存放局部变量,存放局部变量的只是里面的变量表部分。
2,是方法执行产生的内存,每一个方法会创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。
   2.1,局部变量表存放了编译期可知基本数据类型(boolean、bytecharshortintfloatlongdouble)和引用所指向的地址
      (这个地址可能是对象的地址,也可能是对象地址所在的地址(句柄),也可能是指令的地址)
   注意:string类型的值没有存放在这里。这里存放的只是指向堆中或者方法区常量池的地址。
   2.2,局部变量表的内存大小,在编译期就能确定,所以在方法执行时,内存分配后就不会改变了。
3,每一个方法从被调用到执行完成,就是一个栈帧在虚拟机栈中从入栈到出栈的过程。
4,虚拟机栈也是线程独立的。也就是每个线程有自己的栈帧。
5,虚拟机栈可能出现的两种异常:栈溢出和内存溢出。
    如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常(如:将一个函数反复递归自己,最终会出现这种异常)。
    如果JVM栈可以动态扩展(大部分JVM是可以的),当扩展时无法申请到足够内存则抛出OutOfMemoryError异常。

本地方法栈:

 

1)本地方法栈与虚拟机栈所发挥的作用很相似,他们的区别在于虚拟机栈为执行Java代码方法服务,而本地方法栈是为Native方法服务(也就第3方的:c/c++等)。
(2)和JVM栈一样,这个区域也会抛出StackOverflowError和OutOfMemoryError异常。
(3)甚至有的虚拟机(譬如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。

Java堆:

1)是JVM所管理的最大的一块内存。被所有线程共享,在虚拟机启动时创建。(可能存在只被多个线程分配的私有缓冲区)
(2)理论上所有的对象实例以及数组都要在堆上分配。(随着JIT编译器,逃逸分析,栈上分配、标量替换优化技术发展变的不绝对了)。
(3)Java堆是垃圾收集管理的主要战场。现在收集器基本都是采用的分代收集算法,
(Java堆可以细分为:新生代和老年代。再细致分就是把新生代分为:Eden空间、FromSurvivor空间、To Survivor空间。) (
4)Java堆只要逻辑上是连续的即可。 (5)堆的大小是可变的。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

方法区(Method Area)

1)存放的是加载后的字节码,类信息、常量、静态变量、即时编译器编译后的代码等数据 。
   (如:getName、isInterface等方法来获取的数据来源于方法区)
(2)方法区域是全局共享的,比如每个线程都可以访问同一个类的静态变量。
   (虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆))
(2)这块区域主要是针对常量池回收和类型的卸载,值得注意的是JDK1.7已经把常量池转移到堆里面了。
   (由于使用反射机制的原因,虚拟机很难推测哪个类信息不再使用,因此这块区域的回收很难!)
(3)同样,当方法区无法满足内存分配需求时,会抛出OutOfMemoryError。

运行时常量池:之前其空间从方法区域(JDK1.7后为堆空间)中分配

1,它用于存放编译期生成的各种字面量和符号引用。
2,但是Java语言并不要求一定只Class的常量表的内容才能进入方法区常量池,运行期间也可将新内容放入常量池(最典型的String.intern()方法)。
3,当常量池无法在申请到内存时会抛出OutOfMemoryError异常

JVM学习笔记

一点一滴探究 JVM 之内存结构

JVM——Java虚拟机架构

Java内存管理原理及内存区域详解

posted @ 2018-01-25 00:12  假程序猿  阅读(474)  评论(0编辑  收藏  举报