1. 程式人生 > >Eclipse開啟後閃退、異常關閉後,啟動閃退的解決辦法

Eclipse開啟後閃退、異常關閉後,啟動閃退的解決辦法

問題描述:

        32位Win7系統下 Eclipse開啟便閃退,或者稍微維持十幾分鍾或半小時,還是自動關閉,在虛擬機器桌面內同樣的配置和設定就沒有這個問題,我自己電腦3G記憶體就會出現這樣的閃退或者自動關閉。

         我的是maven專案,多個maven子模組同時更新同步svn,也會自動退出,電腦CPU經常100%,實體記憶體使用達到80%。

問題解決:

網搜解決方法,eclipse打不開閃退解決方式
1、通過在命令列中輸入“where java”,找到除jdk目錄下的所有java相關程式,直接刪掉(一般會在C:\WINDOWS\system32下)
2、記憶體不足,開啟Eclipse目錄下的eclipse.ini,把裡面的-Xmx512m改成-Xmx256m
3、檢查環境變數,path變數中將jdk路徑放在最前邊(開頭的“.;”直接後邊)
4、檢查環境變數,path變數中將jdk中的jre路徑放在最前邊(開頭的“.;”直接後邊)
5、傳言中的萬能方案(不過估計非萬能):把jdk目錄下的jre目錄直接複製到eclipse目錄下
6、刪除檔案:[workspace]/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi

7、開啟Eclipse的Windows->Preferences->Java->Compiler,可以看到Eclipse支援的JDK的版本。這裡是1.7,所以,JDK升級到1.8後就會影響這個版本Eclipse的運行了。

8、修改堆記憶體:

-XX:PermSize=2048m     持久帶堆的初始大小
-XX:MaxPermSize=2048M   持久帶堆的最大值

 

我的實驗:

提示刪/修前備份

1.C:\WINDOWS\system32下沒找到java相關程式,也就沒刪。

2.記憶體早已改為768m,所以不是這個問題。

3、4.將jdk、jre放在開頭的“.;”的後面,仍然不解決問題。

5.根據問題實際情況和3、4做的嘗試,肯定不是jdk或jre找不到的問題,我沒嘗試5。

6.刪除檔案:[workspace]/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi,然後重新開啟Eclipse。

Eclipse和工程都正常了(工程不需要重新匯入)。該方案我開啟eclipse一分鐘就閃退,後來我有恢復刪除檔案了。

7.我用的是方案7,可以使得執行時間長一些,但還是偶爾會退出。

8. 我的電腦記憶體是3G,最後我修改了-XX:PermSize=128m  -XX:MaxPermSize=256m,最終解決了,再也沒有出現閃退或者

自動退出。
--------------------- 

引數解釋及相關優化方案:


Ⅰ、記憶體代的優化
-Xms   初始總堆記憶體,預設是實體記憶體的1/64;JVM最大分配的記憶體由-Xmx指定,預設是實體記憶體的1/4。預設空餘堆記憶體小於40%時,JVM就會增大堆直到-Xmx的最大限制;空餘堆記憶體大於70%時,JVM會減少堆直到-Xms的最小限制。因此伺服器一般設定-Xms、-Xmx相等以避免在每次GC 後調整堆的大小。
非堆記憶體分配
-Xmx   最大總堆記憶體,一般設定為實體記憶體的1/4
-Xmn   年輕帶堆記憶體,sun官方推薦為整個堆的3/8
     使用 -Xgcpolicy:gencon 或 -Xgcpolicy:balanced 時,-Xmn 選項相當於設定 -Xmns 和 -Xmnx 選項[IBM]。
     使用 -Xgcpolicy:gencon 時,-Xmnx 設定新區域的最大大小。預設情況下,此選項設定為 -Xmx 選項值的 25%。如果禁用 scavenger,將忽略 -Xmnx 選項[IBM]。
     使用 -Xgcpolicy:balanced 時,-Xmnx 設定 Eden 空間的最大大小。預設情況下,此選項設定為 -Xmx 選項值的 25%[IBM]。
     對於 -Xgcpolicy:gencon 和 -Xgcpolicy:balanced 策略,如果您嘗試同時使用 -Xmnx 和 -Xmn,那麼 JVM 會返回錯誤[IBM]。

-Xmns   選項根據指定的垃圾回收策略,為新區域或 Eden 空間設定初始大小[IBM]。
-Xmnx   選項根據指定的垃圾回收策略,為新區域或 Eden 空間設定最大大小[IBM]。

-Xscmx   指定快取的大小;這個引數只應用於 JVM 建立新快取的情況。如果省略這個選項,那麼選擇一個與平臺相關的預設值(通常是 16MB)。注意,一些作業系統設定可能會限制可分配的共享記憶體量,例如 Linux 上的 SHMMAX 通常設定為大約 20MB[IBM]。
-XX:PermSize=2048m     持久帶堆的初始大小
-XX:MaxPermSize=2048M   持久帶堆的最大大小、根據所需設定。如要編譯jdk這種、因所編譯的類非常多、一定要將該引數設定較大。

例子:

-vmargs:說明後面是VM的引數
-Xms40m:虛擬機器佔用系統的最小記憶體
-Xmx256m:虛擬機器佔用系統的最大記憶體
-XX:PermSize:最小堆大小。一般報記憶體不足時,都是說這個太小,
                       堆空間剩餘小於5%就會警告,建議把這個稍微設
                               大一點,不過要視自己機器記憶體大小來設定
-XX:MaxPermSize:最大堆大小。這個也適當大些
-Xmx512M的5%為25.6M,理論上要求-Xmx的數值與-XX:MaxPermSize必須大於25.6M

1g記憶體推薦為:
-vmargs
-Xms128M
-Xmx512M
-XX:PermSize=64M
-XX:MaxPermSize=128M

疑問解答
  Q:-Xmn、-XX:NewSize/-XX:MaxNewSize、-XX:NewRatio 3組引數都可以影響年輕代的大小,混合使用的情況下,優先順序是什麼?
  A:
    高:-XX:NewSize/-XX:MaxNewSize
    中:-Xmn
    低:-XX:NewRatio
    推薦使用-Xmn引數,原因是這個引數簡潔,相當於一次設定 NewSize/MaxNewSIze,而且兩者相等,適用於生產環境。-Xmn 配合 -Xms/-Xmx,即可將堆記憶體佈局完成。
    -Xmn引數是在JDK 1.4 開始支援。

Ⅱ、位元組碼驗證優化
-Xverify:none(關閉Java位元組碼驗證,從而加快了類裝入的速度)

Ⅲ、預熱方法的快取
-XX:CompileThreshold=100   方法呼叫多少次就會被編譯成本地機器碼
-XX:ParallelGCThreads=4    配置並行收集器的執行緒數,即:同時有多少個執行緒一起進行垃圾回收。此值建議配置與CPU數目相等。

Ⅳ、垃圾回收器選擇
  JVM給出了3種選擇:序列收集器、並行收集器、併發收集器。序列收集器只適用於小資料量的情況,所以生產環境的選擇主要是並行收集器和併發收集器。
  預設情況下JDK5.0以前都是使用序列收集器,如果想使用其他收集器需要在啟動時加入相應引數。JDK5.0以後,JVM會根據當前系統配置進行智慧判斷。

-XX:+DisableExplicitGC   禁用System.gc()的顯示記憶體回收
-XX:+UseParNewGC      使用併發記憶體回收(年輕GC)、關注響應時間。注:另一個年輕GC為: -XX:+UseParallelGC  關注吞吐量
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=80

拓展:Java堆記憶體詳解
JVM堆記憶體分為2塊:Heap Space 和 Permanent Space。

Heap     被劃分成兩個不同的區域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被劃分為三個區域:Eden、From Survivor、To Survivor。

Permanent  即持久代(Permanent Generation),主要存放的是Java類定義資訊,與垃圾收集器要收集的Java物件關係不大。但是在JDK8中該區域已經被移除。


新生代 ( Young )    物件剛創建出來時放在這裡、年輕代的目標就是儘可能快速的收集掉那些生命週期短的物件。年輕代一般分3個區,1個Eden區,2個Survivor區(from 和 to)。

    ·大部分物件在Eden區中生成。當Eden區滿時,還存活的物件將被複制到Survivor區(兩個中的一個),當一個Survivor區滿時,此區的存活物件將被複制到另外一個Survivor區,當另一個Survivor區也滿了的時候,從前一個Survivor區複製過來的並且此時還存活的物件,將可能被複制到年老代。

    ·2個Survivor區是對稱的,沒有先後關係,所以同一個Survivor區中可能同時存在從Eden區複製過來物件,和從另一個Survivor區複製過來的物件;而複製到年老區的只有從另一個Survivor區過來的物件。而且,因為需要交換的原因,Survivor區至少有一個是空的。特殊的情況下,根據程式需要,Survivor區是可以配置為多個的(多於2個),這樣可以增加物件在年輕代中的存在時間,減少被放到年老代的可能。

老年代 ( Old ) 在年輕代中經歷了N次(可配置)垃圾回收後仍然存活的物件,就會被複制到年老代中。因此,可以認為年老代中存放的都是一些生命週期較長的物件。

預設的,新生代 ( Young ) 與老年代 ( Old ) 的比例的值為 1:2 ( 該值可以通過引數 –XX:NewRatio 來指定 ),即:新生代 ( Young ) = 1/3 的堆空間大小。
老年代 ( Old ) = 2/3 的堆空間大小。其中,新生代 ( Young ) 被細分為 Eden 和 兩個 Survivor 區域,這兩個 Survivor 區域分別被命名為 from 和 to,以示區分。
預設的,Edem : from : to = 8 : 1 : 1 ( 可以通過引數 –XX:SurvivorRatio 來設定 ),即: Eden = 8/10 的新生代空間大小,from = to = 1/10 的新生代空間大小。
‍JVM 每次只會使用 Eden 和其中的一塊 Survivor 區域來為物件服務,所以無論什麼時候,總是有一塊 Survivor 區域是空閒著的。
因此,新生代實際可用的記憶體空間為 9/10 ( 即90% )的新生代空間。

持久代( Permanent Generation )   用於存放靜態型別資料,如 Java Class, Method 等。持久代對垃圾回收沒有顯著影響。但是有些應用可能動態生成或呼叫一些Class,例如 hibernate CGLib 等,在這種時候往往需要設定一個比較大的持久代空間來存放這些執行過程中動態增加的型別。

總結:當一組物件生成時,記憶體申請過程:

JVM會試圖為相關Java物件在年輕代的Eden區中初始化一塊記憶體區域。

  當Eden區空間足夠時,記憶體申請結束。否則執行下一步。
  JVM試圖釋放在Eden區中所有不活躍的物件( Young GC )。釋放後若Eden空間仍然不足以放入新物件,JVM則試圖將部分Eden區中活躍物件放入Survivor區。
  Survivor區被用來作為Eden區及年老代的中間交換區域。當年老代空間足夠時,Survivor區中存活了一定次數的物件會被移到年老代。
  當年老代空間不夠時,JVM會在年老代進行完全的垃圾回收( Full GC )。
  Full GC後,若Survivor區及年老代仍然無法存放從Eden區複製過來的物件,則會導致JVM無法在Eden區為新生成的物件申請記憶體,即出現"Out of Memory"。

補足:Out of Memory( OOM )異常一般主要有如下2種原因:

  1. 年老代溢位,表現為:java.lang.OutOfMemoryError:Javaheapspace

  這是最常見的情況,產生的原因可能是:設定的記憶體引數Xmx過小或程式的記憶體洩露及使用不當問題。
  例如迴圈上萬次的字串處理、建立上千萬個物件、在一段程式碼內申請上百M甚至上G的記憶體。還有的時候雖然不會報記憶體溢位,卻會使系統不間斷的垃圾回收,也無法處理其它請求。這種情況下除了檢查程式、列印堆記憶體等方法排查,還可以藉助一些記憶體分析工具,比如MAT就很不錯。

  2. 持久代溢位,表現為:java.lang.OutOfMemoryError:PermGenspace
  通常由於持久代設定過小,動態載入了大量Java類而導致溢位,解決辦法唯有將引數 -XX:MaxPermSize 調大(一般256m能滿足絕大多數應用程式需求)。將部分Java類放到容器共享區(例如Tomcat share lib)去載入的辦法也是一個思路,但前提是容器裡部署了多個應用,且這些應用有大量的共享類庫。

---------------------