龙空技术网

JVM内存区域

探索世界 278

前言:

现在兄弟们对“java资源管理器在哪个文件夹”大致比较关怀,小伙伴们都想要剖析一些“java资源管理器在哪个文件夹”的相关知识。那么小编在网络上网罗了一些对于“java资源管理器在哪个文件夹””的相关文章,希望大家能喜欢,同学们快快来了解一下吧!

程序计数器(Program Counter Register)定义与功能:程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在 Java 虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。特点:它是线程私有的,每个线程都有自己独立的程序计数器。这是因为多线程环境下,各个线程的执行顺序和执行位置是相互独立的,所以每个线程需要有一个单独的计数器来记录自己的执行进度。并且,程序计数器不会出现内存泄漏(OutOfMemoryError)的问题,因为它占用的空间非常小,而且其生命周期和线程的生命周期相同。所以程序计数器一般不存在垃圾回收的情况。举例说明:假设我们有一个简单的 Java 方法public void simpleMethod(){ int a = 1; int b = 2; int c = a + b;},当线程开始执行这个方法的字节码时,程序计数器会从第一条字节码指令开始计数,每执行一条指令,计数器的值就会更新,以指向下一条要执行的指令。Java 虚拟机栈(Java Virtual Machine Stacks)定义与功能:Java 虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是 Java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。局部变量表:它是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。例如,在public int add(int a, int b){ return a + b;}这个方法中,参数a和b就存储在局部变量表中。局部变量表的大小在编译时期就已经确定,并且在方法运行期间不会改变。操作数栈:主要用于存储操作数和中间结果。比如在执行int c = a + b;这个操作时,a和b的值会从局部变量表中取出,压入操作数栈,然后执行加法操作,结果也会存储在操作数栈中。垃圾回收相关:栈帧随着方法的调用和结束而自动入栈和出栈,当一个方法执行完毕,对应的栈帧就会被弹出虚拟机栈,所以栈帧中存储的局部变量表、操作数栈等资源会自动回收,一般不需要专门的垃圾回收机制来处理。但是,如果线程长时间运行,方法不断地入栈,可能会导致栈溢出(StackOverflowError)。如果虚拟机栈可以动态扩展,但是扩展时无法申请到足够的内存,就会抛出OutOfMemoryError。本地方法栈(Native Method Stacks)定义与功能:本地方法栈与 Java 虚拟机栈非常相似,它们之间的主要区别在于 Java 虚拟机栈为 Java 方法(也就是字节码方法)服务,而本地方法栈则为虚拟机使用到的本地方法(Native Method)服务。本地方法是指用非 Java 语言(如 C 或 C++)编写的方法,这些方法通常是为了访问一些底层系统资源或者与外部系统进行交互。例如,在 Java 中调用操作系统的文件读取功能,可能会通过本地方法来实现。垃圾回收相关:和 Java 虚拟机栈类似,本地方法栈中的栈帧在本地方法执行完毕后会自动出栈,资源随之回收。本地方法栈也会出现StackOverflowError和OutOfMemoryError这两种异常情况,原因也是栈深度超出限制或者无法申请到足够的内存来扩展栈,但正常情况下不需要垃圾回收操作来清理资源。堆(Heap)定义与功能:堆是 Java 虚拟机所管理的内存中最大的一块,被所有线程共享。在虚拟机启动时创建,其主要作用是存放对象实例。几乎所有的对象实例(包括数组对象)都在这里分配内存。例如,new Object()、new int[10]这样创建对象和数组的操作,所分配的内存空间都在堆中。垃圾回收(Garbage Collection):因为堆中的对象生命周期各不相同,有的对象可能很快就不再被使用,所以堆是垃圾回收器(Garbage Collector)重点关注的区域。垃圾回收器主要采用分代收集算法,将堆分为新生代(Young Generation)和老年代(Old Generation)。新生代垃圾回收:新生代又可以细分为 Eden 空间、From Survivor 空间和 To Survivor 空间。大部分新创建的对象首先在 Eden 空间分配内存。当 Eden 空间满时,会触发一次 Minor GC(新生代垃圾回收)。在 Minor GC 过程中,存活的对象会被复制到 Survivor 空间(From Survivor 或 To Survivor),并且对象的年龄会加 1。经过多次 Minor GC 后,如果对象的年龄达到一定阈值(通常是 15),就会被晋升到老年代。老年代垃圾回收:老年代的垃圾回收通常称为 Major GC 或者 Full GC。Full GC 的触发条件比较复杂,例如老年代空间不足、永久代(在 JDK 1.7 及以前)或元空间(JDK 1.8 及以后)内存不足、显式调用System.gc()等。Full GC 会对整个堆(包括新生代和老年代)进行垃圾回收,回收效率相对较低,因为需要扫描的对象范围更广,而且可能会导致应用程序出现短暂的停顿(Stop - The - World)现象。如果堆中没有足够的内存来分配新的对象,就会抛出OutOfMemoryError。这种情况可能是因为创建了过多的对象,而且这些对象没有及时被回收,或者是对象的内存占用过大导致的。方法区(Method Area)定义与功能:方法区也是所有线程共享的内存区域。它用于存储已被虚拟机加载的类信息(包括类的版本、字段、方法、接口等信息)、常量、静态变量、即时编译器编译后的代码等。例如,一个类的字节码文件被加载后,其中的类结构信息就会存储在方法区。对于public static final int CONSTANT_VALUE = 10;这样的静态常量,以及public static int staticVariable;这样的静态变量,它们存储的内存空间都在方法区。运行时常量池(Runtime Constant Pool):它是方法区的一部分,主要存放编译期生成的各种字面量和符号引用。字面量包括字符串常量(如"Hello")、基本数据类型的常量(如10、3.14)等。符号引用包括类和接口的全限定名、字段的名称和描述符、方法的名称和描述符等。在类加载后,运行时常量池中的符号引用会被解析为直接引用。JDK 1.8 方法区的变化 - 元空间(Metaspace):在 JDK 1.8 之前,方法区是通过永久代(PermGen)来实现的。永久代有一些问题,例如它的大小是固定的(虽然可以通过一些参数进行调整),容易出现内存溢出的情况。在 JDK 1.8 及以后,使用元空间来代替永久代。元空间使用本地内存,而不是虚拟机内存。这使得方法区的内存大小不再受限于固定的虚拟机内存区域,理论上可以使用的内存空间更大了。垃圾回收相关:在 JDK 1.8 以前的永久代,垃圾回收主要针对常量池中的废弃常量和无用的类。如果一个常量没有任何对象引用它,那么在垃圾回收时就可以被回收。对于类的回收条件比较严格,需要满足该类的所有实例都已经被回收、加载该类的ClassLoader已经被回收、该类对应的java.lang.Class对象没有在任何地方被引用等条件。在 JDK 1.8 的元空间,类元数据的内存管理和垃圾回收机制与永久代有所不同,它的内存分配是由本地内存分配器负责。元空间的垃圾回收主要是卸载不再使用的类元数据,当元空间内存不足时,会抛出OutOfMemoryError,这通常是因为加载了过多的类或者类元数据占用了大量的内存空间。这种变化使得 Java 应用在处理大量类加载的场景下更加稳定,并且减少了因为永久代内存限制而导致的应用崩溃的情况。

标签: #java资源管理器在哪个文件夹