使用JDK的javaagent機制時候,遇到的蛋疼無比的ClassNotFoundException
javaagent機制,也叫Instrumentation,對應JDK原始碼的java.lang.instrument包。這是在JDK5之後提供的新特性,開發者能夠使用這種機制,實現很多有用的功能,比如計算java物件佔用的記憶體大小,實現class檔案的熱替換等。這裡不做過多解釋,主要是我自己才剛接觸,也不懂。可以參考http://blog.csdn.net/qyongkang/article/details/7799603這篇部落格學習下。這裡主要講下,我自己寫程式碼時候遇到的ClassNotFoundException,搞了好久才解決,無比蛋疼。
事情是這樣的,我寫了一個用來獲取Instrumentation
package net.aty.size; import java.lang.instrument.Instrumentation; public class GetSizeAgent { private static volatile Instrumentation globalInstr; public static void premain(String args, Instrumentation inst) { System.out.println("agent run.args=" + args); globalInstr = inst; } public static Instrumentation getInstrumentation() { return globalInstr; } }
然後在測試工程下,呼叫Instrumentation.getObjectSize()計算物件佔用的記憶體大小,原始碼如下:
public static void main(String[] args)
{
Instrumentation instr = GetSizeAgent.getInstrumentation();
System.out.println(instr.getObjectSize(new Integer(100)));
}
之後需要將GetSizeAgent打成jar包,並編寫MANIFEST.MF檔案,內容如下
Manifest-Version: 1.0 Premain-Class: net.aty.size.GetSizeAgent Can-Redefine-Classes: true
然後執行test程式,啟動的時候指定代理jar包:
但是執行測試程式的時候,報了以下錯誤
java.lang.ClassNotFoundException: net.aty.size.GetSizeAgent
FATAL ERROR in native method: processing of -javaagent failed
最終定位的結果是Premain-Class: net.aty.size.GetSizeAgent
類的全路徑後面多了個空格,導致載入代理類的時候報了ClassNotFoundException。實在是覺得很詫異,一般我們在編寫程式碼的時候,都習慣使用StringUtils.trim()類似的方法,清除字串的前後空格。後面上網查了一下,java對MANIFEST.MF檔案格式是有規範的,如果不小心違反了,就會報錯。
大家可以看下java官網的規範:
--jar檔案的Manifest規範
http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html
http://docs.oracle.com/javase/1.5.0/docs/guide/jar/jar.html
http://pages.cs.wisc.edu/~erozner/jdoc/docs/guide/jar/jar.html
http://blog.csdn.net/xiaogugood/article/details/10524183
和http://www.2cto.com/kf/201305/208332.html