JVM内存管理

JVM组成:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存
  • 程序计数器:Java代码被翻译成字节码对应各种字节码指令,当JVM的字节码引擎去执行代码指令时,程序技术器被用来记录当前执行的字节码指令的地址,字节码指示器通过改变计数器的值来选取下一条需要执行的字节码指令。JVM支持多线程,因此每个线程都会有自己的程序计数器,记录这个线程当前执行到哪一条字节码指令了。如果执行的Native方法,计数器为空。该区域没有规定OutOfMemoryError情况。
  • Java虚拟机栈:线程私有,生命周期与线程相同。方法被执行时都会创建一个栈帧,存放局部变量表(基本类型变量,对象引用)、操作栈、动态链接、方法出口等。局部变量表的内存空间在编译器分配,在方法运行期不会改变局部变量表大小。注:逃逸分析后认为该对象不会被其他地方引用的话,且对象小于某个阈值,对象就会在栈上分配,线程请求栈深度大于JVM允许深度抛出StackOverflowError、虚拟机栈扩展时,当无法申请到足够内存抛出OutOfMemoryError
  • 本地方法栈:作用跟异常情况与虚拟机栈相似,但本地方法栈服务于执行Native方法
  • Java堆:内存中最大一块,线程共享,虚拟机启动时创建。存放几乎所有对象实例,它们都在这里分配内存。也是GC的主要区域,也叫GC堆,可分为新生代和老年代。可以处于物理上不连续的内存空间。堆中内存未完成实例分配并堆无法扩展时,抛出OutOfMemoryError
  • 方法区(非堆/永久代):线程共享,存储已被虚拟机加载的类信息、常量、静态变量、编译后的代码。JDK8后常量池被放到堆里,类信息被放到了metaspace(元区域),永久代概念没有了。
  • 运行时常量池:方法区的一部分,存储编译期生成的各种字面量和符号引用,当无法申请到内存时抛出OutOfMemoryError。
JVM运行原理:

  1. 以tomcat部署项目为例,通过类加载器加载类信息到方法区
  2. spring容器利用反射去创建对应类的实例,并将实例对象存放在堆内存
  3. 当浏览器发起请求时,tomcat会为生成线程处理请求,每个线程都有自己的栈内存。
  4. 处理请求执行对象方法,线程执行的每个方法都会按顺序压入栈并生成对应栈帧,方法局部变量都在栈帧中。
  5. 栈帧中的对象引用会去引用在堆内存中的对象实例,实现业务逻辑
  6. 处理完毕,方法移除栈并销毁,释放栈内存空间
注意:计数器记录的是正在执行的jvm字节码指令地址
posted @ 2025-04-16 17:03  难得  阅读(10)  评论(0)    收藏  举报