① java新手 請問各位大神 java類載入器 運行時數據區 有方法區 堆 棧 寄存器 常量池 都什麼含義啊
java類載入:就是把.class文件讀進虛擬機內存,然後按照一定的結構存儲起來,類載入器,就是載入的工具類。
java虛擬機把內存分成
程序計數器:存儲程序運行指令的內存
方法區:存儲java類結構的內存
常量池:存儲java常量的內存
堆:就是存儲new對象的內存
棧:就是保存方法內局部變數的內存
名字都是jvm中翻譯過來的。有本書叫深入java虛擬機。這方面的知識講得比較完全
② Java中,實例中的常量是在堆中還是方法區
java常量池不在堆中也不在棧中,是獨立的內存空間管理。
1. 棧:存放基本類型的變數數據和對象的引用,但對象本身不存放在棧中,而是存放在堆(new 出來的對象)或者常量池中(字元串常量對象存放在常量池中。)
2. 堆:存放所有new出來的對象。
3. 常量池:存放字元串常量和基本類型常量(public static final)。
對於字元串:其對象的引用都是存儲在棧中的,如果是編譯期已經創建好(直接用雙引號定義的)的就存儲在常量池中,如果是運行期(new出來的)才能確定的就存儲在堆中。對於equals相等的字元串,在常量池中永遠只有一份,在堆中有多份。
③ java線程存放在jvm的哪個區域方法又存放在哪個區呢
聊到JAVA中的方法,大多數人對於方法存儲在方法區還是棧區(虛擬機棧)是很迷茫的。其實方法是存在方法區的下面我們就細細說一下JVM中的 方法區 VS 棧區方法區:用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據,方法編譯出的位元組碼也是保存在這
④ Jave運行時常量池是什麼意思
運行時常量池是方法區的一部分,Class文件中除了有類的版本,欄位,方法,介面等信息以外,還有一項信息是常量池用於存儲編譯器生成的各種字面量和符號引用,這部分信息將在類載入後存放到方法區的運行時常量池中。Java虛擬機對類的每一部分(包括常量池)都有嚴格的規定,每個位元組用於存儲哪種數據都必須有規范上的要求,這樣才能夠被虛擬機認可,裝載和執行。一般來說,除了保存Class文件中描述的符號引用外,還會把翻譯出來的直接引用也存儲在運行時常量池中。
⑤ java方法區中包含哪些內容,常量池中包含哪些內容
方法區里存儲著class文件的信息和動態常量池,class文件的信息包括類信息和靜態常量池。可以將類的信息是對class文件內容的一個框架,裡面具體的內容通過常量池來存儲。
動態常量池裡的內容除了是靜態常量池裡的內容外,還將靜態常量池裡的符號引用轉變為直接引用,而且動態常量池裡的內容是能動態添加的。例如調用String的intern方法就能將string的值添加到String常量池中,這里String常量池是包含在動態常量池裡的,但在jdk1.8後,將String常量池放到了堆中。
⑥ java常量池是什麼
常量池(constant pool)指的是在編譯期被確定,並被保存在已編譯的.class文件中的一些數據。它包括了關於類、方法、介面等中的常量,也包括字元串常量。
⑦ Java運行時常量池是什麼
在class文件中,「常量池」是最復雜也最值得關注的內容。
Java是一種動態連接的語言,常量池的作用非常重要,常量池中除了包含代碼中所定義的各種基本類型(如int、long等等)和對象型(如String及數組)的常量值還,還包含一些以文本形式出現的符號引用,比如:
類和介面的全限定名;
欄位的名稱和描述符;
方法和名稱和描述符。
在C語言中,如果一個程序要調用其它庫中的函數,在連接時,該函數在庫中的位置(即相對於庫文件開頭的偏移量)會被寫在程序中,在運行時,直接去這個地址調用函數;
而在Java語言中不是這樣,一切都是動態的。編譯時,如果發現對其它類方法的調用或者對其它類欄位的引用的話,記錄進class文件中的,只能是一個文本形式的符號引用,在連接過程中,虛擬機根據這個文本信息去查找對應的方法或欄位。
所以,與Java語言中的所謂「常量」不同,class文件中的「常量」內容很非富,這些常量集中在class中的一個區域存放,一個緊接著一個,這里就稱為「常量池」。
java中的常量池技術,是為了方便快捷地創建某些對象而出現的,當需要一個對象時,就可以從池中取一個出來(如果池中沒有則創建一個),則在需要重復重復創建相等變數時節省了很多時間。常量池其實也就是一個內存空間,不同於使用new關鍵字創建的對象所在的堆空間。本文只從java使用者的角度來探討java常量池技術,並不涉及常量池的原理及實現方法。個人認為,如果是真的專注java,就必須對這些細節方面有一定的了解。但知道它的原理和具體的實現方法則不是必須的。
常量池中對象和堆中的對象
[java] view plain
public class Test{
Integer i1=new Integer(1);
Integer i2=new Integer(1);
//i1,i2分別位於堆中不同的內存空間
System.out.println(i1==i2);//輸出false
Integer i3=1;
Integer i4=1;
//i3,i4指向常量池中同一個內存空間
System.out.println(i3==i4);//輸出true
//很顯然,i1,i3位於不同的內存空間
System.out.println(i1==i3);//輸出false
}
8種基本類型的包裝類和對象池
java中基本類型的包裝類的大部分都實現了常量池技術,這些類是Byte,Short,Integer,Long,Character,Boolean,另外兩種浮點數類型的包裝類則沒有實現。另外Byte,Short,Integer,Long,Character這5種整型的包裝類也只是在對應值小於等於127時才可使用對象池,也即對象不負責創建和管理大於127的這些類的對象。以下是一些對應的測試代碼:
[java] view plain
public class Test{
public static void main(String[] args){
//5種整形的包裝類Byte,Short,Integer,Long,Character的對象,
//在值小於127時可以使用常量池
Integer i1=127;
Integer i2=127;
System.out.println(i1==i2)//輸出true
//值大於127時,不會從常量池中取對象
Integer i3=128;
Integer i4=128;
System.out.println(i3==i4)//輸出false
//Boolean類也實現了常量池技術
Boolean bool1=true;
Boolean bool2=true;
System.out.println(bool1==bool2);//輸出true
//浮點類型的包裝類沒有實現常量池技術
Double d1=1.0;
Double d2=1.0;
System.out.println(d1==d2)//輸出false
}
}
String也實現了常量池技術
String類也是java中用得多的類,同樣為了創建String對象的方便,也實現了常量池的技術,測試代碼如下:
[java] view plain
public class Test{
public static void main(String[] args){
//s1,s2分別位於堆中不同空間
String s1=new String("hello");
String s2=new String("hello");
System.out.println(s1==s2)//輸出false
//s3,s4位於池中同一空間
String s3="hello";
String s4="hello";
System.out.println(s3==s4);//輸出true
}
}
最後
細節決定成敗,寫代碼更是如此。
在JDK5.0之前是不允許直接將基本數據類型的數據直接賦值給其對應地包裝類的,如:Integer i = 5;
但是在JDK5.0中支持這種寫法,因為編譯器會自動將上面的代碼轉換成如下代碼:Integer i=Integer.valueOf(5);
這就是Java的裝箱.JDK5.0也提供了自動拆箱. Integer i =5; int j = i;
Integer的封裝:
[java] view plain
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
由於cache[]在IntegerCache類中是靜態數組,也就是只需要初始化一次,即static{......}部分,所以,如果Integer對象初始化時是-128~127的范圍,就不需要再重新定義申請空間,都是同一個對象---在IntegerCache.cache中,這樣可以在一定程度上提高效率。
⑧ Java String常量池在什麼位置
需要看你的JVM的版本,不同的JVM版本常量池的位置是不同的!
jdk1,6常量池放在方法區
jdk1.7常量池放在堆內存
jdk1.8放在元空間裡面,和堆相獨立
⑨ Java 中的 常量共享池 什麼意思
一直有個疑問,java中字元串池,String池,共享池是怎麼回事?
好像知道什麼意思,但具體又不太清楚,所以也一直沒太關注。
從網上看了些資料,解釋了下疑問。
在java的棧中,有共享池的概念,把一些常量會放到這個共享池中,包括字元串常量和基本類型常量。
共享的操作時在編譯時 由編譯器完成的,可以節省內存,並提高效率。
例如語句string str = "hello", 首先在棧中創建字元串引用變數str, 再看看棧中有沒有「hello」,如果有就str直接指向它,沒有就創建「hello」並放在棧中,然後指向它。
對於int之類的基本類型的變數也差不多都是這樣的。
而對於 String str = new String("hello"),則是創建新的對象,並放在堆內存中。是在runtime的時候分配內存的。
這樣做效率和節省內存方面不如String str = 「hello」, 但是更靈活,如果編譯時不知道要創建什麼樣的字元串,就
只能運行時創建了。
⑩ java中的字元串到底是在方法區的常量池裡還是new出來的對象里
String str ="nihao";
當這段代碼編譯的時候,首先它會去堆里的方法區常量池裡去查找,如果有一個同樣的字元串「nihao」,存在,那麼它會把當前聲明的對象的地址指向那個字元串對象,調用的是String.itern()方法。如果沒有的話,它會開啟堆內存,分割一塊新的地址指向str對象。
String是不可變的(final的),不必擔心穩定性問題。
而當你新new一個String數組的時候,當你給String數組賦值的時候,它同樣遵循這個原理。
這樣做的好處:字元串多重利用,防止產生冗餘。
詳情參考jdk中String類的的itern方法:
public String intern()
返回字元串對象的規范化表示形式。
一個初始為空的字元串池,它由類 String 私有地維護。
當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字元串(用 equals(Object) 方法確定),則返回池中的字元串。否則,將此 String 對象添加到池中,並返回此 String 對象的引用。
它遵循以下規則:對於任意兩個字元串 s 和 t,當且僅當
s.equals(t) 為 true 時,s.intern()==t.intern() 才為 true。
所有字面值字元串和字元串賦值常量表達式都使用 intern 方法進行操作。