使用java自帶的性能分析工具jvisualvm , 可以方便的查看內(nèi)存, 對象, 線程等多種信息.
成都創(chuàng)新互聯(lián)公司作為成都網(wǎng)站建設(shè)公司,專注重慶網(wǎng)站建設(shè)公司、網(wǎng)站設(shè)計(jì),有關(guān)成都定制網(wǎng)站方案、改版、費(fèi)用等問題,行業(yè)涉及木包裝箱等多個(gè)領(lǐng)域,已為上千家企業(yè)服務(wù),得到了客戶的尊重與認(rèn)可。
win+R????然后輸入???jvisualvm??回車即可
效果如下圖
你可以先用內(nèi)存監(jiān)控工具,進(jìn)行監(jiān)控,看看這個(gè)功能到底用多少內(nèi)存。如果不多,其實(shí)都不需要實(shí)現(xiàn)你說的代碼監(jiān)控的。如果你要使用代碼監(jiān)控,你可是使用Runtime類的幾個(gè)屬性,MaxMemory、FreeMemory、TotalMemory。然后實(shí)現(xiàn)個(gè)線程,在下載pdf功能前開啟線程,然后完畢時(shí)關(guān)閉線程,如果內(nèi)存即將溢出(設(shè)定個(gè)閾值,比如說15%),就報(bào)錯(cuò),跳轉(zhuǎn)到錯(cuò)誤頁面。
通俗的講:
1.基本數(shù)據(jù)類型(四類八種):包裝類的size字段獲得
/*實(shí)際上基本數(shù)據(jù)類型就那四類八種,完全可以記住所占的大小,然后判斷類型直接計(jì)算得到總共占有多少內(nèi)存*/
2.數(shù)組型通過length屬性
3.字符串length()方法
可運(yùn)行代碼:
public
class
Dd
{
public
static
void
main(String
args[]){
int
a=456653;
//int整型,通過包裝類Integer:int--》Ingeger
Integer
ii=new
Integer(a);
//通過Integer類包裝,將簡單類型轉(zhuǎn)換為符合數(shù)據(jù)類型(類),以便通過Integer的靜態(tài)方法size得到二進(jìn)制的位數(shù)。
System.out.println("數(shù)值為:"+ii);
//輸出
System.out.println("二進(jìn)制位數(shù):"+ii.SIZE+"B"+"
"+"所占內(nèi)存字節(jié)數(shù)為:"+ii.SIZE/8+"b");
//所占內(nèi)存大小B:位;b表示字節(jié)。
/*同理可通過基本數(shù)據(jù)類型各自的包裝類求得short--》Short,double--》Double,char--》Character,long--》Long內(nèi)存大小*/
/*實(shí)際上基本數(shù)據(jù)類型就那四類八種,完全可以記住所占的大小,然后判斷類型直接計(jì)算得到總共占有多少內(nèi)存*/
short
shs=34;
Short
shor=new
Short(shs);
System.out.println("數(shù)值為:"+shs);
System.out.println("二進(jìn)制位數(shù):"+shor.SIZE+"B"+"
"+"所占內(nèi)存字節(jié)數(shù)為:"+shor.SIZE/8+"b");
/*數(shù)組類型:通過屬性length獲取*/
int
[]
iis={2,4,3};
System.out.println("數(shù)組大小:"+iis.length+"
內(nèi)存根據(jù)計(jì)算得到");//獲得數(shù)組長度,單位是數(shù)組內(nèi)對象的個(gè)數(shù),具體占多少內(nèi)存要根據(jù)數(shù)組內(nèi)對象元素所占內(nèi)存數(shù)而計(jì)算得到
/*字符串類型的:通過方法length()獲得*/
String
str="hello";
System.out.println(str);
System.out.println("字符串長度:"+str.length()+"
內(nèi)存數(shù)根據(jù)計(jì)算得到");
//獲得字符串長度,單位是字符數(shù)。
//然后根據(jù)中文英文字符占有幾個(gè)字節(jié),數(shù)字占有幾個(gè)字節(jié)計(jì)算得到內(nèi)存大小。
}
}
你說的內(nèi)存空間應(yīng)該是字節(jié)為單位的吧,可以轉(zhuǎn)換成字節(jié)計(jì)算。
說的有點(diǎn)亂,但愿對你能有所幫助
一般來說內(nèi)存泄漏有兩種情況。一種情況,在堆中的分配的內(nèi)存,在沒有將其釋放掉的時(shí)候,就將所有能訪問這塊內(nèi)存的方式都刪掉(如指針重新賦值);另一種情況則是在內(nèi)存對象明明已經(jīng)不需要的時(shí)候,還仍然保留著這塊內(nèi)存和它的訪問方式(引用)。第一種情況,在Java中已經(jīng)由于垃圾回收機(jī)制的引入,得到了很好的解決。所以,Java中的內(nèi)存泄漏,主要指的是第二種情況。
可能光說概念太抽象了,大家可以看一下這樣的例子:
1 Vector v=new Vector(10);
2 for (int i=1;i100; i++){
3 Object o=new Object();
4 v.add(o);
5 o=null;
6 }
在這個(gè)例子中,代碼棧中存在Vector對象的引用v和Object對象的引用o。在For循環(huán)中,我們不斷的生成新的對象,然后將其添加到Vector對象中,之后將o引用置空。問題是當(dāng)o引用被置空后,如果發(fā)生GC,我們創(chuàng)建的Object對象是否能夠被GC回收呢?答案是否定的。因?yàn)椋珿C在跟蹤代碼棧中的引用時(shí),會發(fā)現(xiàn)v引用,而繼續(xù)往下跟蹤,就會發(fā)現(xiàn)v引用指向的內(nèi)存空間中又存在指向Object對象的引用。也就是說盡管o引用已經(jīng)被置空,但是Object對象仍然存在其他的引用,是可以被訪問到的,所以GC無法將其釋放掉。如果在此循環(huán)之后,Object對象對程序已經(jīng)沒有任何作用,那么我們就認(rèn)為此Java程序發(fā)生了內(nèi)存泄漏。
盡管對于C/C++中的內(nèi)存泄露情況來說,Java內(nèi)存泄露導(dǎo)致的破壞性小,除了少數(shù)情況會出現(xiàn)程序崩潰的情況外,大多數(shù)情況下程序仍然能正常運(yùn)行。但是,在移動設(shè)備對于內(nèi)存和CPU都有較嚴(yán)格的限制的情況下,Java的內(nèi)存溢出會導(dǎo)致程序效率低下、占用大量不需要的內(nèi)存等問題。這將導(dǎo)致整個(gè)機(jī)器性能變差,嚴(yán)重的也會引起拋出OutOfMemoryError,導(dǎo)致程序崩潰。
請確保java_home/bin配置到path環(huán)境變量下,因?yàn)檫@些工具都在jdk的bin目錄下
jps(JVM Process Status Tool):JVM機(jī)進(jìn)程狀況工具
用來查看基于HotSpot JVM里面所有進(jìn)程的具體狀態(tài), 包括進(jìn)程ID,進(jìn)程啟動的路徑等等。與unix上的ps類似,用來顯示本地有權(quán)限的java進(jìn)程,可以查看本地運(yùn)行著幾個(gè)java程序,并顯示他們的進(jìn)程號。使用jps時(shí),不需要傳遞進(jìn)程號做為參數(shù)。
Jps也可以顯示遠(yuǎn)程系統(tǒng)上的JAVA進(jìn)程,這需要遠(yuǎn)程服務(wù)上開啟了jstat服務(wù),以及RMI注及服務(wù),不過常用都是對本對的JAVA進(jìn)程的查看。
命令格式:jps [ options ] [ hostid ]
常用參數(shù)說明:
-m 輸出傳遞給main方法的參數(shù),如果是內(nèi)嵌的JVM則輸出為null。
-l 輸出應(yīng)用程序主類的完整包名,或者是應(yīng)用程序JAR文件的完整路徑。
-v 輸出傳給JVM的參數(shù)。
例如:
C:\Users\Administratorjps -lmv
1796 -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -XX:MaxPermSize=256m
7340 sun.tools.jps.Jps -lmv -Denv.class.path=.;D:\DevTools\VM\jdk1.6.0_31\\lib\dt.jar;D:\DevTools\VM\jdk1.6.0_31\\lib\tools.jar; -Dapplication.home=D:\DevTools\VM\jdk1.6.0_31 -Xms8m
其中pid為1796的是我的eclipse進(jìn)程,pid為7340的是jps命令本身的進(jìn)程
jinfo(Configuration Info for Java):JVM配置信息工具
可以輸出并修改運(yùn)行時(shí)的java 進(jìn)程的opts。用處比較簡單,用于輸出JAVA系統(tǒng)參數(shù)及命令行參數(shù)
命令格式:jinfo [ options ] [ pid ]
常用參數(shù)說明:
-flag 輸出,修改,JVM命令行參數(shù)
例如:
C:\Users\Administratorjinfo 1796
將會打印出很多jvm運(yùn)行時(shí)參數(shù)信息,由于比較長這里不再打印出來,可以自己試試,內(nèi)容一目了然
Jstack(Stack Trace for Java):JVM堆棧跟蹤工具
jstack用于打印出給定的java進(jìn)程ID或core file或遠(yuǎn)程調(diào)試服務(wù)的Java堆棧信息,如果是在64位機(jī)器上,需要指定選項(xiàng)"-J-d64“
命令格式:jstack [ option ] pid
常用參數(shù)說明:
-F 當(dāng)’jstack [-l] pid’沒有相應(yīng)的時(shí)候強(qiáng)制打印棧信息
-l 長列表. 打印關(guān)于鎖的附加信息,例如屬于java.util.concurrent的ownable synchronizers列表.
-m 打印java和native c/c++框架的所有棧信息.
-h | -help打印幫助信息
例如:
C:\Users\Administratorjstack 1796
2013-05-22 11:42:38
Full thread dump Java HotSpot(TM) Client VM (20.6-b01 mixed mode):
"Worker-30" prio=6 tid=0x06514c00 nid=0x1018 in Object.wait() [0x056af000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.eclipse.core.internal.jobs.WorkerPool.sleep(WorkerPool.java:188)
- locked 0x1ad84a90 (a org.eclipse.core.internal.jobs.WorkerPool)
at org.eclipse.core.internal.jobs.WorkerPool.startJob(WorkerPool.java:220)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:50)
......
......
......
......
jstat(JVM statistics Monitoriing Tool):JVM統(tǒng)計(jì)信息監(jiān)視工具
對Java應(yīng)用程序的資源和性能進(jìn)行實(shí)時(shí)的命令行的監(jiān)控,包括了對Heap size和垃圾回收狀況的監(jiān)控
命令格式:jstat [ option pid [interval [ s | ms ] [count] ] ]
常用參數(shù)說明:
-gcutil 輸出已使用空間占總空間的百分比
-gccapacity 輸出堆中各個(gè)區(qū)域使用到的最大和最小空間
例如:每隔1秒監(jiān)控jvm內(nèi)存一次,共監(jiān)控5次
C:\Users\Administratorjstat -gccapacity 1796 1s 5
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 97
C:\Users\Administratorjstat -gcutil 1796 1s 5
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
一些術(shù)語的中文解釋:
S0C:年輕代中第一個(gè)survivor(幸存區(qū))的容量 (字節(jié))
S1C:年輕代中第二個(gè)survivor(幸存區(qū))的容量 (字節(jié))
S0U:年輕代中第一個(gè)survivor(幸存區(qū))目前已使用空間 (字節(jié))
S1U:年輕代中第二個(gè)survivor(幸存區(qū))目前已使用空間 (字節(jié))
EC:年輕代中Eden(伊甸園)的容量 (字節(jié))
EU:年輕代中Eden(伊甸園)目前已使用空間 (字節(jié))
OC:Old代的容量 (字節(jié))
OU:Old代目前已使用空間 (字節(jié))
PC:Perm(持久代)的容量 (字節(jié))
PU:Perm(持久代)目前已使用空間 (字節(jié))
YGC:從應(yīng)用程序啟動到采樣時(shí)年輕代中g(shù)c次數(shù)
YGCT:從應(yīng)用程序啟動到采樣時(shí)年輕代中g(shù)c所用時(shí)間(s)
FGC:從應(yīng)用程序啟動到采樣時(shí)old代(全gc)gc次數(shù)
FGCT:從應(yīng)用程序啟動到采樣時(shí)old代(全gc)gc所用時(shí)間(s)
GCT:從應(yīng)用程序啟動到采樣時(shí)gc用的總時(shí)間(s)
NGCMN:年輕代(young)中初始化(最小)的大小 (字節(jié))
NGCMX:年輕代(young)的最大容量 (字節(jié))
NGC:年輕代(young)中當(dāng)前的容量 (字節(jié))
OGCMN:old代中初始化(最小)的大小 (字節(jié))
OGCMX:old代的最大容量 (字節(jié))
OGC:old代當(dāng)前新生成的容量 (字節(jié))
PGCMN:perm代中初始化(最小)的大小 (字節(jié))
PGCMX:perm代的最大容量 (字節(jié))
PGC:perm代當(dāng)前新生成的容量 (字節(jié))
S0:年輕代中第一個(gè)survivor(幸存區(qū))已使用的占當(dāng)前容量百分比
S1:年輕代中第二個(gè)survivor(幸存區(qū))已使用的占當(dāng)前容量百分比
E:年輕代中Eden(伊甸園)已使用的占當(dāng)前容量百分比
O:old代已使用的占當(dāng)前容量百分比
P:perm代已使用的占當(dāng)前容量百分比
S0CMX:年輕代中第一個(gè)survivor(幸存區(qū))的最大容量 (字節(jié))
S1CMX :年輕代中第二個(gè)survivor(幸存區(qū))的最大容量 (字節(jié))
ECMX:年輕代中Eden(伊甸園)的最大容量 (字節(jié))
DSS:當(dāng)前需要survivor(幸存區(qū))的容量 (字節(jié))(Eden區(qū)已滿)
TT: 持有次數(shù)限制
MTT : 最大持有次數(shù)限制
jmap( Memory Map for Java):JVM內(nèi)存映像工具
打印出某個(gè)java進(jìn)程(使用pid)內(nèi)存內(nèi)的所有‘對象’的情況(如:產(chǎn)生那些對象,及其數(shù)量)
命令格式:jmap [ option ] pid
常用參數(shù)說明:
-dump:[live,]format=b,file=filename 使用二進(jìn)制形式輸出jvm的heap內(nèi)容到文件中, live子選項(xiàng)是可選的,假如指定live選項(xiàng),那么只輸出活的對象到文件.
-histo[:live] 打印每個(gè)class的實(shí)例數(shù)目,內(nèi)存占用,類全名信息. VM的內(nèi)部類名字開頭會加上前綴”*”. 如果live子參數(shù)加上后,只統(tǒng)計(jì)活的對象數(shù)量.
-F 強(qiáng)迫.在pid沒有相應(yīng)的時(shí)候使用-dump或者-histo參數(shù). 在這個(gè)模式下,live子參數(shù)無效.
例如:以二進(jìn)制形式輸入當(dāng)前堆內(nèi)存映像到文件data.hprof中
jmap -dump:live,format=b,file=data.hprof 1796
生成的文件可以使用jhat工具進(jìn)行分析,在OOM(內(nèi)存溢出)時(shí),分析大對象,非常有用
通過使用如下參數(shù)啟動JVM,也可以獲取到dump文件:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./java_pidpid.hprof
在jvm發(fā)生內(nèi)存溢出時(shí)生成內(nèi)存映像文件
jhat(JVM Heap Analysis Tool):JVM堆轉(zhuǎn)儲快照分析工具
用于對JAVA heap進(jìn)行離線分析的工具,他可以對不同虛擬機(jī)中導(dǎo)出的heap信息文件進(jìn)行分析,如LINUX上導(dǎo)出的文件可以拿到WINDOWS上進(jìn)行分析,可以查找諸如內(nèi)存方面的問題。
命令格式:jhat dumpfile(jmap生成的文件)
例如:分析jmap導(dǎo)出的內(nèi)存映像
jhat data.hprof
執(zhí)行成功后,訪問即可查看內(nèi)存信息,
MAT(Memory Analyzer Tool):一個(gè)基于Eclipse的內(nèi)存分析工具
官網(wǎng):
update:
這是eclipse的一個(gè)插件,安裝后可以打開xxx.hprof文件,進(jìn)行分析,比jhat更方便使用,有些時(shí)候由于線上xxx.hprof文件過大,直接使用jhat進(jìn)行初步分析了,可以的話拷貝到本地分析效果更佳。
圖形化監(jiān)控工具:
在JDK安裝目錄bin下面有兩個(gè)可視化監(jiān)控工具
1. JConsole(Java Monitoring and Management Console) 基于JMX的可視化管理工具。
2. VisualVM(All-in-one Java Troubleshooting Tool)隨JDK發(fā)布的最強(qiáng)大的運(yùn)行監(jiān)視和故障處理程序。
推薦使用VisualVM,他有很多插件,可以更方便的監(jiān)控運(yùn)行時(shí)JVM
java程序大家都知道,內(nèi)存溢出是經(jīng)常見的錯(cuò)誤,下面從基本的開始分析!
內(nèi)存溢出是由于沒被引用的對象(垃圾)過多造成JVM沒有及時(shí)回收,造成的內(nèi)存溢出。如果出現(xiàn)這種現(xiàn)象可行代碼排查:
一)是否App中的類中和引用變量過多使用了Static修飾 如public staitc Student s;在類中的屬性中使用 static修飾的最好只用基本類型或字符串。如public static int i = 0; //public static String str;
二)是否App中使用了大量的遞歸或無限遞歸(遞歸中用到了大量的建新的對象)
三)是否App中使用了大量循環(huán)或死循環(huán)(循環(huán)中用到了大量的新建的對象)
四)檢查App中是否使用了向數(shù)據(jù)庫查詢所有記錄的方法。即一次性全部查詢的方法,如果數(shù)據(jù)量超過10萬多條了,就可能會造成內(nèi)存溢出。所以在查詢時(shí)應(yīng)采用“分頁查詢”。
五)檢查是否有數(shù)組,List,Map中存放的是對象的引用而不是對象,因?yàn)檫@些引用會讓對應(yīng)的對象不能被釋放。會大量存儲在內(nèi)存中。
六)檢查是否使用了“非字面量字符串進(jìn)行+”的操作。因?yàn)镾tring類的內(nèi)容是不可變的,每次運(yùn)行"+"就會產(chǎn)生新的對象,如果過多會造成新String對象過多,從而導(dǎo)致JVM沒有及時(shí)回收而出現(xiàn)內(nèi)存溢出。
如String s1 = "My name";
String s2 = "is";
String s3 = "xuwei";
String str = s1 + s2 + s3 +.........;這是會容易造成內(nèi)存溢出的
但是String str = "My name" + " is " + " xuwei" + " nice " + " to " + " meet you"; //但是這種就不會造成內(nèi)存溢出。因?yàn)檫@是”字面量字符串“,在運(yùn)行"+"時(shí)就會在編譯期間運(yùn)行好。不會按照J(rèn)VM來執(zhí)行的。
在使用String,StringBuffer,StringBuilder時(shí),如果是字面量字符串進(jìn)行"+"時(shí),應(yīng)選用String性能更好;如果是String類進(jìn)行"+"時(shí),在不考慮線程安全時(shí),應(yīng)選用StringBuilder性能更好。
知道原因了,解決起來就非常簡單了。
當(dāng)前題目:java代碼查內(nèi)存 查看java進(jìn)程的內(nèi)存
轉(zhuǎn)載注明:http://www.yijiale78.com/article26/hhsdcg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄、ChatGPT、服務(wù)器托管、品牌網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)公司、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)