1. 栈区
栈区用于保存基本数据类型对象和自定义对象的引用。当在一个代码块定义一个变量时,java就会在栈区为这个变量分配内存空间。当该变量退出作用域后,java会立即释放为该变量分配的内存空间。
每一个线程都有一个栈区,栈区是线程私有的,其他的栈无法访问。
2. 堆区
堆区用于存放所有new出来的对象和数组,由java的内存回收机制管理堆区的对象内存分配。堆区的对象与栈区的对象引用往往是成对的,栈区的对象引用指向堆区的对象或数组在堆内存中的首地址。栈区的对象引用相当于为堆区的对象起了一个别名,程序就可以使用栈区的对象引用来访问堆区的对象。堆区的对象或数组,在没有引用变量指向它的时候,会变为垃圾,不再被使用,但仍占据堆区的内存,由垃圾回收机制在一定时间后自动清理。
堆区是所有线程共享的,这就意味着多个线程的栈区的多个引用变量,可以引用同一个堆区的对象或数组。
下图表示栈区的引用变量到堆区对象的指向。
3. 方法区(静态区)
一个类的类型信息,通常被存储在方法区。类型信息是指由类加载器在类的加载时从类文件中提取出来的类数据结构等信息。一个类的静态变量也会被保存在方法区。
通常类的类型信息在方法区会保存如下信息:
- 类的基本信息:类的完整名称,类的父类的完整名称,类的修饰符等。
- 该类的常量池:jvm会为每一个类维护一个常量池,用于存储该类需要用到的常量。
- 域信息:即成员变量信息,包括名称,类型,修饰符等。
- 方法信息:方法逻辑、方法名、方法的返回类型、方法参数的数量和类型(有序的)和方法的修饰符。
- 类变量:即静态变量。静态变量只有类相关,与具体实例无关,即使该类无具体实例也可以调用静态变量。
方法区是堆区的逻辑组成部分
最后附一张网上找来的图