JVM java运行时区域

这里写图片描述

程序计数器

程序计数器是一块较小的内存空间,他的作用可以看做是当前线程所执行的字节码的行号指示器。

程序计数器是可以当做java执行(一个线程)的指示器,执行下一条指令,选择那一条路径,是否循环操作等都是依赖这个指示器来执行的

java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间来实现的,在任何一个确定的时刻,一个处理器或内核都只会执行一条线程的指令,因此为了线程能够恢复到正确的执行位置,每条线程都要有一个独立的程序计数器,并且不同线程中的程序计数器互不影响,也就是说 程序计数器是线程私有的

程序计数器是唯一一个在虚拟机中没有内存溢出的区域。

JAVA虚拟机栈

与程序计数器一样,JAVA虚拟机栈也是线程私有,并且生命周期与线程相同。
虚拟机栈主要存储的是方法相关的内容(方法参数、局部变量、对象引用等);

本地方法栈

本地方法栈为虚拟机使用到的native方法服务。


java堆

java堆是java虚拟机管理的最大一块内存,被线程共享。虚拟机垃圾收集器的主要区域。
作用:几乎所有的对象内存空间都在堆上分配。
特点:
1、从内存回收的角度看,由于现在的垃圾收集器基本采用分代回收,java堆还可以细分为老年代和新生代,新生代又可以分为eden、FromSurvivor和ToSurvivor。
(图示所说的永久代,在hotspot虚拟机中就是方法区。但两者并不等价,只是HotSpot将gc分代收集扩展至方法区,或者说用永久代来实现方法区)

这里写图片描述

2、从内存分配角度看,线程共享的java堆中可能划分出多个线程共有的缓冲区(Thread Local Allocation Buffer,TLAB)。
无论从哪个角度看,java堆都是存储的对象实例,进一步划分都是为了更好的分配和回收内存。

方法区

方法区和java堆一样,也是线程共享的区域。
作用:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
特点:同java堆一样不需要连续的内存和可以选择固定大小或者可扩展;可以选择不实现垃圾收集;相对而言,方法区的垃圾收集比较少见,但是并不保证“永久”存在。方法区的垃圾回收目标主要是针对常量池的回收和对类型的卸载(相对类加载而言)。

扫描二维码关注公众号,回复: 2381405 查看本文章

JDK8中,使用metaspace将其取代。

运行时常量池

是方法区的一部分。

在.class文件中除了类信息外,还有一项就是常量池,用于存放编译器形成的各种字面量和符号引用,这部分内容将在类加载后进入运行时常量池中存放。

java虚拟机对class文件格式有着严格的规范要求,只有符合规范的class文件才能被虚拟机装载和执行,但对于运行时常量池,java虚拟机规范没有做任何要求,不同实现的虚拟机可以自己实现这个内存区域。
运行时常量池相对于class文件常量池的另一个特征就是具备动态性,运行期间也可以将新的常量置于池中,并非一定是class文件中的常量。

比如String类的intern方法, 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。

异常

1、StackOverflowError
源代码解释说:抛出这个错误是因为递归太深.其实真正的原因是因为Java线程操作是基于栈的,当调用方法内部方法也就是进行一次递归的时候就会把当前方法压入栈直到方法内部的方法执行完全之后,就会返回上一个方法,也就是出栈操作执行上一个方法。

2、OutOfMemoryError
源代码解释说:因为内存溢出,JVM不能分配给对象的创建空间.并且GC也不能够回收足够的空间.当你创建对象的速度快于JVM回收空间的时候就会发生空间不足这个问题:

总结:
StackOverflowError:递归过深,递归没有出口。
OutOfMemoryError:JVM空间溢出,创建对象速度高于GC回收速度。

猜你喜欢

转载自blog.csdn.net/xiaojin21cen/article/details/79860507
今日推荐