內存溢出錯誤、jvm配置、java.lang.OutOfMemoryError

最近在做數據抽取用到多線程,前期java.lang.OutOfMemoryError的錯誤,後面排查,發現代碼中有的資源沒有及時關閉,部分代碼沒有最優化,還有線程控制的不合理,優化後但有個程序的內存釋放太慢,使用內存一直處於增長狀態,沒有及時釋放資源,就用下面的代碼強制釋放內存,每隔十秒若處於阻塞狀態主動釋放

                        //latch.await();//線程阻塞
                        //上面一段代碼和下面的代碼是一個意思
                        
                        while (!latch.await(10, TimeUnit.SECONDS)) {
                            System.out.println("FreeMem(" + Runtime.getRuntime().freeMemory() + ") maxMem(" + Runtime.getRuntime().maxMemory() + ") totalMem(" + Runtime.getRuntime().totalMemory() + ")");
                            System.gc();
                            System.runFinalization();
                        }

Linux命令窗口,執行命令:top,可查看內存使用情況,一般是res那一列。 

maxMemory()這個方法返回的是java虛擬機(這個進程)能構從操作系統那裏挖到的最大的內存,以字節爲單位,如果在運行java程序的時 候,沒有添加-Xmx參數,那麼就是64兆,也就是說maxMemory()返回的大約是64*1024*1024字節,這是java虛擬機默認情況下能 從操作系統那裏挖到的最大的內存。如果添加了-Xmx參數,將以這個參數後面的值爲準,例如java -cp ClassPath -Xmx512m ClassName,那麼最大內存就是512*1024*0124字節。

totalMemory()這個方法返回的是java虛擬機現在已經從操作系統那裏挖過來的內存大小,也就是java虛擬機這個進程當時所佔用的所有 內存。如果在運行java的時候沒有添加-Xms參數,那麼,在java程序運行的過程的,內存總是慢慢的從操作系統那裏挖的,基本上是用多少挖多少,直 挖到maxMemory()爲止,所以totalMemory()是慢慢增大的。如果用了-Xms參數,程序在啓動的時候就會無條件的從操作系統中挖- Xms後面定義的內存數,然後在這些內存用的差不多的時候,再去挖。

freeMemory()是什麼呢,剛纔講到如果在運行java的時候沒有添加-Xms參數,那麼,在java程序運行的過程的,內存總是慢慢的從操 作系統那裏挖的,基本上是用多少挖多少,但是java虛擬機100%的情況下是會稍微多挖一點的,這些挖過來而又沒有用上的內存,實際上就是 freeMemory(),所以freeMemory()的值一般情況下都是很小的,但是如果你在運行java程序的時候使用了-Xms,這個時候因爲程 序在啓動的時候就會無條件的從操作系統中挖-Xms後面定義的內存數,這個時候,挖過來的內存可能大部分沒用上,所以這個時候freeMemory()可 能會有些大。
 

因爲服務器開啓較多的線程,將虛擬機的內存加大了,在tomcat的bin文件夾中的catalina.sh添加了以下內容:

JAVA_OPTS=" -Xms1024m -Xmx2048 "

設置Tomcat啓動的初始內存
其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項。

java jvm 的參數設置參考:

要加“m”說明是MB,否則就是KB了,在啓動tomcat時會 報內存不足。
-Xms:初始值
-Xmx:最大值
-Xmn:最小值
Windows
在catalina.bat最前面加入
set JAVA_OPTS=-Xms128m -Xmx350m
如果用startup.bat啓動tomcat,OK設置生效.夠成功的分配200M內存.
但是如果不是執行startup.bat啓動tomcat而是利用windows的系統服務啓動tomcat服務,上面的設置就不生效了,
就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M內存就OOM了..
windows服務執行的是bin\tomcat.exe.他讀取註冊表中的值,而不是catalina.bat的設置.
解決辦法:
修改註冊表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions
原值爲
-Dcatalina.home="C:\ApacheGroup\Tomcat 5.0"
-Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 5.0\common\endorsed"
-Xrs
加入 -Xms300m -Xmx350m
重起tomcat服務,設置生效

 

system.gc()和system.runFinalization()區別作用:

System.gc(); //告訴垃圾收集器打算進行垃圾收集,而垃圾收集器進不進行收集是不確定的 

System.runFinalization(); //強制調用已經失去引用的對象的finalize方法 

 

java中的finalize()方法

當垃圾收集器認爲沒有指向對象實例的引用時,會在銷燬該對象之前調用finalize()方法。該方法最常見的作用是確保釋放實例佔用的全部資源。java並不保證定時爲對象實例調用該方法,甚至不保證方法會被調用,所以該方法不應該用於正常內存處理。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章