• 检测多个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的问题,代码不复杂,换了一个实现思路帮助解决了实际问题。

     

     工具下载

  • 相关阅读:
    tx:advice标签简介
    spring tx:advice 和 aop:config 配置事务
    java web开发 高并发处理
    log4j输出多个自定义日志文件,动态配置路径
    接口(interface) 可以 new()吗???~
    观察者模式
    BLOB的读写操作
    JAVA Timer定时器使用方法
    判断webservice是否可用
    二十三、oracle pl/sql分类三 包
  • 原文地址:https://www.cnblogs.com/Lawson/p/2984343.html
Copyright © 2020-2023  润新知