JAVA的JVM內(nèi)存空間分為三個(gè)重要區(qū)域:堆杭隙、棧和方法區(qū)
棧區(qū)
線程私有。每個(gè)線程有自己的棧區(qū)因妙,棧中只保存了方法中的局部變量數(shù)據(jù)痰憎,包括了局部變量的基礎(chǔ)數(shù)據(jù)類型和對象實(shí)例的引用。
- 更具體地說攀涵,在線程私有區(qū)的虛擬機(jī)棧中铣耘,會在每個(gè) Java 方法執(zhí)行的同時(shí)創(chuàng)建一個(gè)棧幀用于存儲局部變量表、操作數(shù)棧以故、常量池引用等信息
棧中數(shù)據(jù)都是私有的蜗细,其他棧不可以訪問
通過下面代碼,觀察棧中是否有分配對象內(nèi)存
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() 方法內(nèi):" + a);
return a;
}
public static void foo() {
ClassA a = new ClassA(2);
System.out.println("foo() 方法內(nèi):" + a);
}
public static void main(String[] args) {
ClassA classA = getClassA(1);
System.out.println("main() 方法內(nèi):" + classA);
foo();
}
}
結(jié)果:
getA() 方法內(nèi):bean.ClassA@2503dbd3
main() 方法內(nèi):bean.ClassA@2503dbd3
foo() 方法內(nèi):bean.ClassA@4b67cf4d
沒有調(diào)用finalize方法怒详,可以說明foo()實(shí)例化的對象沒有隨著foo()方法的出棧而銷毀炉媒,即foo()方法內(nèi)實(shí)例化的局部對象并沒有分配內(nèi)存在棧上
堆區(qū):
JVM中有句關(guān)于堆的解釋
The heap is the runtime data area from which memory for all class instances and arrays is allocated踪区。
堆是所有的對象實(shí)例以及數(shù)組分配內(nèi)存的運(yùn)行時(shí)數(shù)據(jù)區(qū)域。
所有線程共享橱野。存儲了全部的對象實(shí)例朽缴,即所有的對象都在這里分配內(nèi)存。而每個(gè)實(shí)例都有一個(gè)與之對應(yīng)的class信息存到方法區(qū)中水援。
堆中存放的對象本身密强,包括了成員變量和局部變量,除此外還有成員變量的引用和成員變量的基本數(shù)據(jù)類型蜗元。
方法區(qū):
所有線程共享或渤。用于存儲被虛擬機(jī)加載的類信息、常量奕扣、靜態(tài)變量薪鹦、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。
虛擬機(jī)把它當(dāng)成永久代來進(jìn)行垃圾回收惯豆。但很難確定永久代的大小池磁,因?yàn)樗艿胶芏嘁蛩赜绊懀⑶颐看?Full GC 之后永久代的大小都會改變楷兽,所以經(jīng)常會拋出 OutOfMemoryError 異常地熄。為了更容易管理方法區(qū),從 JDK 1.8 開始芯杀,移除永久代端考,并把方法區(qū)移至元空間,它位于本地內(nèi)存中揭厚,而不是虛擬機(jī)內(nèi)存中却特。