JVM相关问题
問:堆和棧有什么區(qū)別
答:堆是存放對象的,但是對象內(nèi)的臨時變量是存在棧內(nèi)存中,如例子中的methodVar是在運行期存放到棧中的。
棧是跟隨線程的,有線程就有棧,堆是跟隨JVM的,有JVM就有堆內(nèi)存。
?
問:堆內(nèi)存中到底存在著什么東西?
答:對象,包括對象變量以及對象方法。
?
問:類變量和實例變量有什么區(qū)別?
答:靜態(tài)變量是類變量,非靜態(tài)變量是實例變量,直白的說,有static修飾的變量是靜態(tài)變量,沒有static修飾的變量是實例變量。靜態(tài)變量存在方法區(qū)中,實例變量存在堆內(nèi)存中。
?
問:我聽說類變量是在JVM啟動時就初始化好的,和你這說的不同呀!
答:那你是道聽途說,信我的,沒錯。
?
問:Java的方法(函數(shù))到底是傳值還是傳址?
答:都不是,是以傳值的方式傳遞地址,具體的說原生數(shù)據(jù)類型傳遞的值,引用類型傳遞的地址。對于原始數(shù)據(jù)類型,JVM的處理方法是從Method Area或Heap中拷貝到Stack,然后運行frame中的方法,運行完畢后再把變量指拷貝回去。
?
問:為什么會產(chǎn)生OutOfMemory產(chǎn)生?
答:一句話:Heap內(nèi)存中沒有足夠的可用內(nèi)存了。這句話要好好理解,不是說Heap沒有內(nèi)存了,是說新申請內(nèi)存的對象大于Heap空閑內(nèi)存,比如現(xiàn)在Heap還空閑1M,但是新申請的內(nèi)存需要1.1M,于是就會報OutOfMemory了,可能以后的對象申請的內(nèi)存都只要0.9M,于是就只出現(xiàn)一次OutOfMemory,GC也正常了,看起來像偶發(fā)事件,就是這么回事。???????但如果此時GC沒有回收就會產(chǎn)生掛起情況,系統(tǒng)不響應(yīng)了。
?
問:我產(chǎn)生的對象不多呀,為什么還會產(chǎn)生OutOfMemory?
答:你繼承層次忒多了,Heap中?產(chǎn)生的對象是先產(chǎn)生?父類,然后才產(chǎn)生子類,明白不?
?
問:OutOfMemory錯誤分幾種?
答:分兩種,分別是“OutOfMemoryError:java heap size”和”O(jiān)utOfMemoryError: PermGen space”,兩種都是內(nèi)存溢出,heap size是說申請不到新的內(nèi)存了,這個很常見,檢查應(yīng)用或調(diào)整堆內(nèi)存大小。
“PermGen space”是因為永久存儲區(qū)滿了,這個也很常見,一般在熱發(fā)布的環(huán)境中出現(xiàn),是因為每次發(fā)布應(yīng)用系統(tǒng)都不重啟,久而久之永久存儲區(qū)中的死對象太多導(dǎo)致新對象無法申請內(nèi)存,一般重新啟動一下即可。
?
問:為什么會產(chǎn)生StackOverflowError?
答:因為一個線程把Stack內(nèi)存全部耗盡了,一般是遞歸函數(shù)造成的。
?
問:一個機器上可以看多個JVM嗎?JVM之間可以互訪嗎?
答:可以多個JVM,只要機器承受得了。JVM之間是不可以互訪,你不能在A-JVM中訪問B-JVM的Heap內(nèi)存,這是不可能的。在以前老版本的JVM中,會出現(xiàn)A-JVM Crack后影響到B-JVM,現(xiàn)在版本非常少見。
?
問:為什么Java要采用垃圾回收機制,而不采用C/C++的顯式內(nèi)存管理?
答:為了簡單,內(nèi)存管理不是每個程序員都能折騰好的。
?
問:為什么你沒有詳細(xì)介紹垃圾回收機制?
答:垃圾回收機制每個JVM都不同,JVM Specification只是定義了要自動釋放內(nèi)存,也就是說它只定義了垃圾回收的抽象方法,具體怎么實現(xiàn)各個廠商都不同,算法各異,這東西實在沒必要深入。
?
問:JVM中到底哪些區(qū)域是共享的?哪些是私有的?
答:Heap和Method Area是共享的,其他都是私有的,
?
問:什么是JIT,你怎么沒說?
答:JIT是指Just In Time,有的文檔把JIT作為JVM的一個部件來介紹,有的是作為執(zhí)行引擎的一部分來介紹,這都能理解。Java剛誕生的時候是一個解釋性語言,別噓,即使編譯成了字節(jié)碼(byte code)也是針對JVM的,它需要再次翻譯成原生代碼(native code)才能被機器執(zhí)行,于是效率的擔(dān)憂就提出來了。Sun為了解決該問題提出了一套新的機制,好,你想編譯成原生代碼,沒問題,我在JVM上提供一個工具,把字節(jié)碼編譯成原生碼,下次你來訪問的時候直接訪問原生碼就成了,于是JIT就誕生了,就這么回事。
?
問:JVM還有哪些部分是你沒有提到的?
答:JVM是一個異常復(fù)雜的東西,寫一本磚頭書都不為過,還有幾個要說明的:
常量池(constant pool):按照順序存放程序中的常量,并且進(jìn)行索引編號的區(qū)域。比如int i =100,這個100就放在常量池中。
安全管理器(Security Manager):提供Java運行期的安全控制,防止惡意攻擊,比如指定讀取文件,寫入文件權(quán)限,網(wǎng)絡(luò)訪問,創(chuàng)建進(jìn)程等等,Class Loader在Security Manager認(rèn)證通過后才能加載class文件的。
方法索引表(Methods table),記錄的是每個method的地址信息,Stack和Heap中的地址指針其實是指向Methodstable地址。
??????
問:為什么不建議在程序中顯式的生命System.gc()?
答:因為顯式聲明是做堆內(nèi)存全掃描,也就是Full GC,是需要停止所有的活動的(Stop??TheWorld Collection),你的應(yīng)用能承受這個嗎?
?
問:JVM有哪些調(diào)整參數(shù)?
答:非常多,自己去找,堆內(nèi)存、棧內(nèi)存的大小都可以定義,甚至是堆內(nèi)存的三個部分、新生代的各個比例都能調(diào)整。
問:jvm 運行時的數(shù)據(jù)區(qū)和哪些是線程公用的:
答:圖中五大區(qū)域就是運行時的內(nèi)存區(qū),其中棧被分為虛擬機棧和本地方法棧,虛擬機棧是java自己碼方法對應(yīng)的棧,而本地方法是c代碼方法對應(yīng)的棧。
其中綠色圈起來的是不可以公用的,是線程獨自創(chuàng)建和占用的,這個涉及具體的線程執(zhí)行。
來自jameswxx 樵夫后院的博客
總結(jié)
- 上一篇: DNF100级天帝怎么加点 100级天帝
- 下一篇: 树形数据结构