标签:取消 切换 静态变量 时间片 cpu img ogr operator 的区别
JVM 在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。如下图所示:
程序计数器(Program Counter Register)
是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。例如,分支、循环、跳转、异常、线程恢复等都依赖于计数器。
当执行的线程数量超过 CPU 数量时,线程之间会根据时间片轮询争夺 CPU 资源。如果一个线程的时间片用完了,或者是其它原因导致这个线程的 CPU 资源被提前抢夺,那么这个退出的线程就需要单独的一个程序计数器,来记录下一条运行的指令,从而在线程切换后能恢复到正确的执行位置。各条线程间的计数器互不影响,独立存储,我们称这类内存区域为 “线程私有” 的内存。
?? 注意:此内存区域是唯一一个在 JVM 中没有规定任何
OutOfMemoryError
情况的区域。
Java 虚拟机栈(Java Virtual Machine Stacks)
也是线程私有的,它的生命周期与线程相同。
每个 Java 方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储 局部变量表、操作数栈、常量池引用 等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
ReturnAddress
类型。?? 注意:该区域可能抛出以下异常:
- 如果线程请求的栈深度超过最大值,就会抛出
StackOverflowError
异常;- 如果虚拟机栈进行动态扩展时,无法申请到足够内存,就会抛出
OutOfMemoryError
异常。?? 提示:可以通过
-Xss
这个虚拟机参数来指定一个程序的 Java 虚拟机栈内存大小java -Xss=512M HackTheJava
本地方法栈(Native Method Stack)
与虚拟机栈的作用相似。
二者的区别在于:虚拟机栈为 Java 方法服务;本地方法栈为 Native 方法服务。本地方法并不是用 Java 实现的,而是由 C 语言实现的。
?? 注意:本地方法栈也会抛出
StackOverflowError
异常和OutOfMemoryError
异常。
Java 堆(Java Heap)
的作用就是存放对象实例,几乎所有的对象实例都是在这里分配内存。
Java 堆是垃圾收集的主要区域(因此也被叫做"GC 堆")。现代的垃圾收集器基本都是采用分代收集算法,该算法的思想是针对不同的对象采取不同的垃圾回收算法。
因此虚拟机把 Java 堆分成以下三块:
新生代(Young Generation)
Eden
- Eden 和 Survivor 的比例为 8:1From Survivor
To Survivor
老年代(Old Generation)
永久代(Permanent Generation)
当一个对象被创建时,它首先进入新生代,之后有可能被转移到老年代中。新生代存放着大量的生命很短的对象,因此新生代在三个区域中垃圾回收的频率最高。
?? 注意:Java 堆不需要连续内存,并且可以动态扩展其内存,扩展失败会抛出
OutOfMemoryError
异常。?? 提示:可以通过
-Xms
和-Xmx
两个虚拟机参数来指定一个程序的 Java 堆内存大小,第一个参数设置初始值,第二个参数设置最大值。java -Xms=1M -Xmx=2M HackTheJava
方法区(Method Area)也被称为永久代。方法区用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现。
?? 注意:和 Java 堆一样不需要连续的内存,并且可以动态扩展,动态扩展失败一样会抛出
OutOfMemoryError
异常。?? 提示:
- JDK 1.7 之前,HotSpot 虚拟机把它当成永久代来进行垃圾回收。可通过参数
-XX:PermSize
和-XX:MaxPermSize
设置。- JDK 1.8 之后,取消了永久代,用 **
metaspace(元数据)
**区替代。可通过参数-XX:MaxMetaspaceSize
设置。
运行时常量池(Runtime Constant Pool)
是方法区的一部分,Class 文件中除了有类的版本、字段、方法、接口等描述信息,还有一项信息是常量池(Constant Pool Table),用于存放编译器生成的各种字面量和符号引用,这部分内容会在类加载后被放入这个区域。
final
的常量值等。除了在编译期生成的常量,还允许动态生成,例如 String
类的 intern()
。这部分常量也会被放入运行时常量池。
?? 注意:当常量池无法再申请到内存时会抛出
OutOfMemoryError
异常。
直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是 JVM 规范中定义的内存区域。
在 JDK 1.4 中新加入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer
对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
?? 注意:直接内存这部分也被频繁的使用,且也可能导致
OutOfMemoryError
异常。?? 提示:直接内存容量可通过
-XX:MaxDirectMemorySize
指定,如果不指定,则默认与 Java 堆最大值(-Xmx
指定)一样。
内存区域 | 内存作用范围 | 异常 |
---|---|---|
程序计数器 | 线程私有 | 无 |
Java 虚拟机栈 | 线程私有 | StackOverflowError 和 OutOfMemoryError |
本地方法栈 | 线程私有 | StackOverflowError 和 OutOfMemoryError |
Java 堆 | 线程共享 | OutOfMemoryError |
方法区 | 线程共享 | OutOfMemoryError |
运行时常量池 | 线程共享 | OutOfMemoryError |
直接内存 | 非运行时数据区 | OutOfMemoryError |
标签:取消 切换 静态变量 时间片 cpu img ogr operator 的区别
原文地址:https://www.cnblogs.com/turbosha/p/13246179.html