其中线程私有的是(1)(2)(3)
a.每个线程都有,为了在多线程切换时,回到自己之前的位置
b.寄存器里边指定了下一条需要执行的指令
c.执行Java代码时,保存当前指令的地址
d.不会有OOM的情况
e.native方法为空
1.每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应一个栈帧在虚拟机栈中入栈和出栈的过程。
2. 之前我们一直讲的栈区域实际上就是此处的虚拟机栈,再详细一点,是虚拟机栈中的局部变量表部分。
3.此区域一共会产生以下两种异常:
1. 如果线程请求的栈深度大于虚拟机所允许的深度(-Xss设置栈容量),将会抛出StackOverFlowError异常。
2. 虚拟机在动态扩展时无法申请到足够的内存,会抛出OOM(OutOfMemoryError)异常
每个方法执行时创建一个栈帧用于存储:
a.局部变量表:8种基本数据类型、对象引用、字节码指令地址。内存在编译期间分配
b.操作数栈:从局部变量种取出数据,深度在编译期间确定
c.动态链接:符号引用
d.方法返回地址:方法出口
与虚拟机栈作用一样,区别是本地方法栈执行Native方法,而虚拟机栈
为JVM执行的Java方法服务。
线程共享区域(4)(5)
a.在JVM启动时创建,所有的对象实例以及数组都要在堆上分配。
b.如果在堆中没有足够的内存完成实例分配并且堆也无法再拓展时,将会抛出OOM。
c.可以动态扩展OOM(年轻代、老年代、永久代-元空间)
a.用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
b.此区域的内存回收主要是针对常量池的回收以及对类型的卸载。当方法区无法满足内存分配需求时,将抛出OOM异常。
a.编译期及运行期间产生的常量被放在运行时常量池中。
b.这里所说的常量包括:基本类型、包装类(包装类不管理浮点型,整形只会管理-128到127)和String。
c.类加载时,会查询字符串常量池,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。
常量池补充说明
常量池可以分为 Class文件常量池、运行时常量池、字符串常量池:
a.Class文件常量池
Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
b.运行时常量池
运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法。
c.字符串常量池
存储字符串对象,或是字符串对象的引用。
a.在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
b.直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,肯定还是会受到本机总内存(包括RAM以及SWAP区或者分页文件)大小以及处理器寻址空间的限制。也可能导致OutOfMemoryError异常出现。
**JVM垃圾回收发生在堆和方法区,Java进程在启动后会创建垃圾回收线程,来对内存中无用的对象进行回收。
**
给对象分配一个引用计数器,每当有地方引用它时,计数+1,当引用失效时,计数-1。当某个对象的计数为0时,就不能被引用了,人认为对象已死。
缺点:当两个对象循环引用时,无法回收
任务所有对象都是从“GC Roots”的对象作为起始点(树根节点),从这些节点出发向下搜索,可以遍历到的对象就是“可达对象”,遍历的路径称为“GC Roots引用链”。当某个对象与GC Roots之间没有引用链时,就认为该对象不可达,这些对象会被认为是可以回收的对象
将内存分为容量相等的两块,每次只使用其中一块,当这一块用完了,就将还活着的对象复制到另外一块上,然后把已使用的内存空间一次性清理掉
优点:实现简单,因为每次都是堆整个半区进行回收,因此就不会产生内存碎片
缺点:内存利用率低,只能用一半
(1)先标记出要回收的对象
(2)标记完成后,统一回收这些对象
优点:不需要额外的空间
缺点:回产生内存碎片
(1)先标记出要回收的对象
(2)标记完成后,统一回收这些对象
(3)让存活的对象向一端移动
(1)对象优先在Eden区分配
(2)大对象直接进入老年代:大量来纳许空间的对象,如很长的字符串以及数组
(3)长期存活的对象将进入老年代MaxTenuringThreshold
(4)动态判定对象年龄,并不总是按照MaxTenuringThreshold才能晋升到老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代
(5)空间分配担保:
今天看String\StringBuilder\StringBuffer时,遇到了字符串常量池这个名词,虽然之前听过,但没有细究过它到底是存在哪里。
于是在网上搜寻了一番,说的我都挺懵,但看到一篇自我感觉比较清晰详细的文章,在这里–》
总的来说就是,JDK1.7之前,运行时常量池(字符串常量池也在里边)是存放在方法区,此时方法区的实现是永久带。
JDK1.7字符串常量池被单独从方法区移到堆中,运行时常量池剩下的还在永久带(方法区)
JDK1.8,永久带更名为元空间(方法区的新的实现),但字符串常量池池还在堆中,运行时常量池在元空间(方法区)。