檢測多個Jar包沖突的class


當一個項目使用的jar越來越多,代碼經常在運行的時候拋出異常:java.lang.NoSuchMethodExceptionjava.lang.NoSuchFieldError,基本是存在多個jar包包含相同的class類文件導致的,運行期可能用的class沒有該方法等。

 

一、思路

為了提前找到存在相同classjar包,我准備寫一個小程序,由於是操作jar包等,需要用Java代碼來處理,但寫出來一般是一個class文件,使用者可能需要用命令行執行的方式來調用它,java的桌面程序我不擅長,於是想到了用.NET開發一個工具殼子,內部調用java代碼的方式來執行,開始想到用.NET下的IKVM來處理jar包,它提供了java基礎包的.NET實現。但加載它也會使程序增大幾M。最后我換了個思路,代碼由Java來編寫,.NETjava命令的方式執行java編寫的class文件,再把輸出內容展現到.NET工具的界面上,這樣也會大大減小工具的大小。

 

二、技術實現:

新增一個java的控制台程序,它有默認main方法入口,需要傳遞待分析的Jar包路徑,參數是通過外界傳入的,這里會從.net界面輸入參數傳遞到javamain入口,如代碼:

public static void main(String[] args) {

if(args.length < 1){

System.out.println("請輸入jar包路徑!");

return;

}

然后根據傳入的args的路徑,獲取該路徑下的所有jar包文件,然后輪詢所有jar包,獲取里面存在的class文件,然后把jar包和對應的class文件放到一個字典類里,輪詢所有jar包后,就可以通過字典類獲取存在一個class多個jar包的文件。字典類結構為:HashMap<String,HashSet<String>>,用class名稱作為key,這里比如為com/apache/abc/demo.class,多個jar包的名稱做為value,達到鍵唯一,值是集合的字典,方便后續從字典輸出存在多個jar包值的class,結構如下:

Key

Value(HashSet)

org/apache/taglibs/standard/lang/jstl/ImplicitObjects.class

 

standard-1.1.2.jar

jstl-1.2.jar

...

...

...

 

主要實現代碼如:

File file = new File(args[0]);

Map<String,HashSet<String> > jarMap = new HashMap<String,HashSet<String>>();

if(null != file &&  file.exists() && file.isDirectory()){

File[] jarFile = file.listFiles();

for(File f : jarFile){

if(f.isFile() && f.getName().endsWith(".jar")){

try {

JarFile jar = new JarFile(f);

Enumeration<JarEntry> enumJar = jar.entries();

while(enumJar.hasMoreElements()){

JarEntry je = enumJar.nextElement();

if(je.getName().endsWith(".class")){

if(jarMap.containsKey(je.getName())){

jarMap.get(je.getName()).add(f.getName());

}else{

HashSet<String> set = new HashSet<String>();

set.add(f.getName());

jarMap.put(je.getName(), set);

 

查找重復類代碼如下:

for(String s : keys){

if(jarMap.get(s).size() > 1){

//存在重復

HashSet<String> hsfile = jarMap.get(s);

String sfiles = "";

for(String sf : hsfile){

sfiles = sfiles + sf + ",";

}

if(sfiles.length() > 1){

sfiles = sfiles.substring(0, sfiles.length() -1);

}

System.out.println(sfiles + "有重復類:" + s);

}

}

最后java程序輸出

System.out.println("[[over]]");

這里的作用是打一個結束標記,.NET代碼根據這個結束標記顯示內容。

Java代碼會把查找到的jar包和沖突的類輸出到控制台,.NET可以根據執行后的控制台字符串稍作處理然后展現出來。.NET通過新啟一個Process調用cmd執行命令的方式調用Java指令,代碼如下:

        public static string RunCmd(string command)

        {

            System.Diagnostics.Process p = new System.Diagnostics.Process();

            p.StartInfo.FileName = "cmd.exe";

            p.StartInfo.UseShellExecute = false;        

            p.StartInfo.RedirectStandardInput = true;   

            p.StartInfo.RedirectStandardOutput = true;  

            p.StartInfo.RedirectStandardError = true;   

            p.StartInfo.CreateNoWindow = true;

            p.Start();

            p.StandardInput.WriteLine(command);       

            p.StandardInput.WriteLine("exit");

            string result = p.StandardOutput.ReadToEnd();        

            p.WaitForExit(); p.Close();

            return result;

        }

指令傳入:java Checksame + “界面錄入的路徑”,軟件界面如:

  

上面就完成了檢測jar包存在多個class的問題,代碼不復雜,換了一個實現思路幫助解決了實際問題。

 

 工具下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM