網(wǎng)上關(guān)于該題目的文章已經(jīng)很多,我覺(jué)得把它們幾個(gè)關(guān)聯(lián)起來(lái)講可能更好理解一下。與其它語(yǔ)言一樣,它在執(zhí)行我們寫(xiě)的程序前要先分配內(nèi)存空間,以便于存放代碼、數(shù)據(jù);程序的執(zhí)行過(guò)程其實(shí)依然是代碼的執(zhí)行及數(shù)據(jù)的讀寫(xiě)過(guò)程;除了在執(zhí)行我們寫(xiě)的顯式的可見(jiàn)代碼外,Jvm還會(huì)自動(dòng)幫我們幫一些事,包括類的加載、初始化、GC等,這些也不特殊。以下分別來(lái)說(shuō)下這些概念。
這一點(diǎn)基本上同其它高級(jí)語(yǔ)言一樣,Java包含:堆、棧、本地棧(有些特殊)、永久代碼區(qū)。以下具體說(shuō)下每個(gè)內(nèi)存區(qū)的作用及使用方式 概念 修改方式 永久代碼區(qū) 其實(shí)代碼兩個(gè)字是我加上去的,它并不是單單存放代碼,但代碼的確是最主要、最典型的、對(duì)于一個(gè)類A,不論實(shí)例化多少對(duì)象,它的代碼區(qū)有始自終都只有一塊。這個(gè)區(qū)包含的主要是類的信息、比如static字段,final常量(跟編譯器還是有些關(guān)系),各種方法(包括static及無(wú)static修飾的)二進(jìn)制天書(shū)等,這一區(qū)域往往在整個(gè)JVM執(zhí)行過(guò)程中大小不變。 XX:PermSpace 本地棧 用于java native線程,也就是用jni里添加的線程使用的棧,因?yàn)楸救藳](méi)寫(xiě)過(guò)多少jni代碼,這塊不詳說(shuō)。 ? 棧 說(shuō)到棧必須關(guān)聯(lián)線程,線程包含我們平時(shí)常用的主線程main、及我們調(diào)用Thread.start()運(yùn)行起來(lái)的一般線程,一個(gè)線程一個(gè)棧;棧的作用大家應(yīng)該清楚,就是用來(lái)保留我們線程執(zhí)行的現(xiàn)場(chǎng),包括:調(diào)用者函數(shù)的局部變量、參數(shù)等;棧的特色是存放的東西都很小,存取速度很快。 Xss 堆 堆,應(yīng)該是內(nèi)存是占用最大的一個(gè)部分,跟據(jù)jvm的配置不同,堆可占到j(luò)vm總使用內(nèi)存的95%以上,當(dāng)然這個(gè)數(shù)字沒(méi)多大意義,只是給大家一個(gè)感覺(jué),相對(duì)于其它語(yǔ)言,Java里的堆比較好理解,所有我們new出來(lái)的對(duì)象都存放在堆里,而它的使用者通過(guò)"引用"來(lái)調(diào)用它,引進(jìn)會(huì)經(jīng)常被壓入之前我們提到的棧里(引用很小,所以很適合在棧里進(jìn)進(jìn)出出)。 Xms 初始大小 及 Xmn 年輕代大小?
permanent space
及
XX:MaxPermSpace
native stack
stack
及
-XX:MainThreadStackSize
heap
及
Xmx 最大值
?
*注意:32位的機(jī)器內(nèi)存設(shè)置的總合一般不能大于1.5G(即使你有4G的物理內(nèi)存,可能跟java的尋址方式有關(guān);是否有其它解決方案,還望高人給出)
我這里舉個(gè)例子
public class Demo { // 永久代碼區(qū) <- 類總體信息
public static String staticField; // 永久代碼區(qū)
public String dynField; // 堆
public static void staticMtd() { // 永久代碼區(qū) <- 代碼塊
int i = 0; //直接量引用(程序員不可見(jiàn))往往在寄存器里,或是其它臨時(shí)的地方
String str = ""; //str的實(shí)例在堆里
System.out. }
public void mtd() { // 永久代碼區(qū) <- 代碼塊(但加了訪問(wèn)限制,只有用對(duì)象才能引用到該代碼塊)
}
}
完成了這部分,剩下的兩部分就想對(duì)簡(jiǎn)單了:
類在第一次使用之前被加載初始化,具體怎么加載取決于運(yùn)行環(huán)境。類的初始化即在永久代碼區(qū)里為類及字段分配內(nèi)存空間,然后再跟據(jù)我們的書(shū)寫(xiě)順序依次賦值或執(zhí)行static塊。
比如:
static{ System.out.println("first exc"); }
static String Field = "x";
static String F2 = Field;
static{System.out.println("after F2=Field");}
//賦值及執(zhí)行順序就是書(shū)寫(xiě)順序。
構(gòu)造子類之前必須調(diào)用父類,且構(gòu)造塊會(huì)構(gòu)造函數(shù)之前執(zhí)行(很想知道具體是怎么實(shí)現(xiàn)的,望大師指點(diǎn))
舉個(gè)例子:
A類:
public class A {
static {
System.out.println("A static block");
}
public A() {
super();
System.out.println("A constructor");
}
{
System.out.println("A not static block" + this);
}
}
B類:
public class B extends A {
static {
System.out.println("B static block");
}
public B() {
super();
System.out.println("B constructor");
}
{
System.out.println("B not static block");
}
public static void main(String[] args) {
new B();
}
}
結(jié)果:
A static block
B static block
A not static blockB@a90653
A constructor
B not static block
B constructor
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注