JVM和运行时数据区

目录

运行时数据区

元空间

[Java 虚拟机栈](#Java 虚拟机栈)

[java 堆](#java 堆)

程序计数器

本地方法栈

JVM

JVM是Java Virtual Machine的简称,是java程序的运行环境(二进制字节码的运行环境)。主要由三个子系统构成,分别是类加载子系统、运行时数据区和执行引擎。

JVM结构图

运行时数据区

运行时数据区是由元空间、堆、程序计数器、虚拟机栈、本地方法栈五部分组成。

元空间

用于存储已被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据的区域。被所有线程共享,多个线程可以同时访问方法区中的类信息和常量等。

在 JDK 7 及以前的实现方式,它和堆一样,都是 JVM 内存的一部分,并且有固定的大小限制。永久代不仅存储类的元数据,还存储了字符串常量池等信息。从 JDK 8 开始,永久代被元空间取代。元空间不再使用 JVM 的内存,而是使用本地内存,这使得元空间的大小不再受 JVM 内存大小的限制,而是受限于操作系统的可用内存。同时,字符串常量池从方法区移动到了堆中

在 JDK 8 之前,如果方法区(永久代)的内存设置过小,可能会导OutOfMemoryError: PermGen space 错误。在 JDK 8 及以后,如果元空间的内存使用超过了限制,会抛出OutOfMemoryError: Metaspace 错误。

Java 虚拟机栈

每个 Java 线程在创建时都会分配一个独立的虚拟机栈,用于存储方法参数和方法内部定义的局部变量。每个栈由多个栈帧组成,对应这每次方法调用时占用的内存,栈帧过多会导致栈内存溢出,常见于递归调用。

java 堆

用于保存对象实例、数组等,使得程序可以动态地创建和使用对象。为了高效地进行垃圾回收,堆通常被分为不同的区域,常见的分代垃圾回收机制将堆分为新生代和老年代。其中,新生代又可进一步细分为 Eden 区和两个 Survivor 区。新创建的对象通常会首先分配在 Eden 区,经过多次垃圾回收后仍然存活的对象会被移动到老年代。

程序在申请内存时,如果堆没有足够的内存空间供其使用,就会出现内存溢出的情况,从而导致程序抛出OutOfMemoryError异常。程序在运行过程中,如果由于某些原因导致一些不再使用的对象无法被垃圾回收器回收,一直占用内存空间,会使得可用内存逐渐减少,这时就会出现内存泄漏的情况。

程序计数器

用于保存字节码的行号,记录正在执行的字节码指令地址。每个 Java 线程都有自己独立的程序计数器,可以在执行过程中独立记录自己的执行位置,不受到其他线程的干扰。

本地方法栈

与 Java 虚拟机栈类似,本地方法栈是为虚拟机使用到的本地方法服务的。本地方法是使用非 Java 语言(如 C、C++)实现的方法,通常用于与操作系统底层交互或调用其他本地库。每个线程都有自己独立的本地方法栈,与 Java 虚拟机栈相互独立。

和 Java 虚拟机栈一样,本地方法栈也可能会抛出 StackOverflowErrorOutOfMemoryError 异常。当本地方法调用层次过深或无法申请到足够的内存时,就会触发相应的异常。

相关推荐
果壳~10 分钟前
【Java】mybatis-plus乐观锁与Spring重试机制
java·spring·mybatis
MARSERERER27 分钟前
Starrocks Full GC日志分析
java
只在空想家39 分钟前
Servlet 快速入门
java·后端·servlet
fakaifa1 小时前
【最新版】西陆洗车系统源码全开源+uniapp前端+搭建教程
java·小程序·uni-app·php·源码下载·西陆洗车·洗车小程序
shenyan~1 小时前
关于 smali:2. 从 Java 到 Smali 的映射
java·开发语言
一只叫煤球的猫1 小时前
实习生踩坑记:Redis分布式锁为什么总是"失效"?看门狗机制深度解析
java·后端·性能优化
浪客川1 小时前
生成JavaDoc文档
java
橘子青衫1 小时前
解锁多线程编程:深入探索同步容器与并发容器
java·后端
攒了一袋星辰1 小时前
Spring @Value注解的依赖注入实现原理
java·后端·spring