JVM内存区域的一些理解

JAVA的JVM内存空间分为三个重要区域:堆、栈和方法区

image.png

栈区

线程私有。每个线程有自己的栈区,栈中只保存了方法中的局部变量数据,包括了局部变量的基础数据类型和对象实例的引用。

  • 更具体地说,在线程私有区的虚拟机栈中,会在每个 Java 方法执行的同时创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息

栈中数据都是私有的,其他栈不可以访问

通过下面代码,观察栈中是否有分配对象内存

public class ClassA{
     public int arg;
     public ClassA(int arg) {
         this.arg = arg;
     }

     @Override
     protected void finalize() throws Throwable {
         System.out.println("对象即将被销毁: " + this + "; arg = " + arg);
         super.finalize();
     }
 }
 
 
 public class TestCase1 {
     public static ClassA getClassA(int arg) {
         ClassA a = new ClassA(arg);
         System.out.println("getA() 方法内:" + a);
         return a;
     }
 
     public static void foo() {
         ClassA a = new ClassA(2);
         System.out.println("foo() 方法内:" + a);
     }
 
 
     public static void main(String[] args) {
         ClassA classA = getClassA(1);
         System.out.println("main() 方法内:" + classA);
 
         foo();
     }
 
 }

结果:

getA() 方法内:bean.ClassA@2503dbd3
main() 方法内:bean.ClassA@2503dbd3
foo() 方法内:bean.ClassA@4b67cf4d

没有调用finalize方法,可以说明foo()实例化的对象没有随着foo()方法的出栈而销毁,即foo()方法内实例化的局部对象并没有分配内存在栈上

堆区:

JVM中有句关于堆的解释

The heap is the runtime data area from which memory for all class instances and arrays is allocated。
堆是所有的对象实例以及数组分配内存的运行时数据区域。

所有线程共享。存储了全部的对象实例,即所有的对象都在这里分配内存。而每个实例都有一个与之对应的class信息存到方法区中。

堆中存放的对象本身,包括了成员变量和局部变量,除此外还有成员变量的引用和成员变量的基本数据类型。

方法区:

所有线程共享。用于存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

虚拟机把它当成永久代来进行垃圾回收。但很难确定永久代的大小,因为它受到很多因素影响,并且每次 Full GC 之后永久代的大小都会改变,所以经常会抛出 OutOfMemoryError 异常。为了更容易管理方法区,从 JDK 1.8 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。

参考资料

CyC2018 CS-Notes JAVA虚拟机
Java是否可以栈上分配对象内存? 为什么?

你可能感兴趣的:(JVM内存区域的一些理解)