精华内容
下载资源
问答
  • 2018-07-07 00:45:12

    使用URLClassLoader加载不同Jar包中的相同包名相同类名的类

    开发中会遇到这种情况,使用一项功能需要依赖jar,然而一段时间后这些包升级,包名和类名均不变的情况下功能发生变化。旧的jar依然需要使用,而新功能却需要使用新升级的jar。这时如果依赖两个包,使用时会造成冲突。因此需要进行jar隔离。有很多的隔离框架可以使用,如jarlinks。本文将演示通过URLClassLoader加载器来进行隔离的基本方法,而实应用中的的一些隔离框架中也会看到此种方式的使用。

    首先原有系统内部依赖version782.jar包,并用到该包中的RequestHead类。而此时又希望用到version713.jar包中的RequestHead类。直接增加maven依赖会产生冲突,这里通过URLClassLoader进行加载。

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import xxx.RequestHead;
    import org.apache.commons.codec.binary.Hex;
    
    import java.io.File;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    
    public class ClassLoadTest {
    
        public static void main(String[] args) throws Exception {
            URL url = new File("/version713.jar").toURI().toURL();
            // 创建URLClassLoader,并设置父加载器为null,这样通过加载器加载
            // 类时就不会通过父加载器去通过classpath中加载version782.jar
            // 中的RequestHead
            URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}, null);
    
            // 加载version713.jar包中的RequestHead类
            Class<?> clz = urlClassLoader.loadClass("xxx.RequestHead");
            // 加载序列化工具类,由于要通过反射调用ProtoBufferCore中的方法
            // 而且需要指定Class参数,这个参数需要与ProtoBufferCore使用相同
            // 的类加载器,因此后续加载参数CtripBusinessBean
            Class<?> pb = urlClassLoader.loadClass("xxx.ProtoBufferCore");
            // 加载参数CtripBusinessBean,调用ProtoBufferCore方法时使用
            Class<?> ctripBizBean = urlClassLoader.loadClass("xxx.CtripBusinessBean");
    
            RequestHead head782 = new RequestHead();
            Object head713 = clz.newInstance();
    
            Object pbObject = pb.newInstance();
    
            System.out.println(pbObject);
            System.out.println(JSON.toJSONString(head713, SerializerFeature.WriteNullStringAsEmpty));
            System.out.println(JSON.toJSONString(head782, SerializerFeature.WriteNullStringAsEmpty));
    
            clz.getField("appId").set(head713,"999111");
            // 这里进行方法调用时,执行参数上文中加载的ctripBizBean,
            // 这样才能保证正确调用
            Method toByteArrayMethod = pb.getMethod("toByteArray",ctripBizBean);
            String hex = Hex.encodeHexString((byte[]) toByteArrayMethod.invoke(pbObject,head713));
            System.out.println(hex);
        }
    }

    参考

    java虚拟机规范5.3节

    更多相关内容
  • 这里所说的冲突,是指类的包名和类型完全相同的时候希望同时使用相同类的不同版本)。 参考地址:https://baijiahao.baidu.com/s?id=1636309817155065432&wfr=spider&for=pc 处理思路:见上图,使用...

    背景:在引入第三方jar包以后,偶尔会遇到不同jar包中的类冲突。这里所说的冲突,是指类的包名和类型完全相同(有的时候希望同时使用相同类的不同版本)。

    参考地址:https://baijiahao.baidu.com/s?id=1636309817155065432&wfr=spider&for=pc

    处理思路:见上图,使用原生的类加载是实现不了这个功能的,需要使用自定义类加载器,分别从不同jar中或者目录加载class文件,然后进行实例化,最后使用反射来调用(因Class动态变化,所以需要反射机制)

    代码实现:

    package com.mp.util;
     
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLClassLoader;
     
    public class MyClassloader extends ClassLoader {
     
      private String libPath;
     
      public MyClassloader(String path) {
        libPath = path;
      }
     
      @Override
      public Class<?> findClass(String name) throws ClassNotFoundException {
        if (libPath.endsWith(".zip") || libPath.endsWith(".jar")) {
          try {
            return this.loadClassFromJarOrZip(name);
          } catch (MalformedURLException e) {
            e.printStackTrace();
          }
        }
        String fileName = getFileName(name);
        File file = new File(libPath, fileName);
        try (FileInputStream is = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
          int len = 0;
          while ((len = is.read()) != -1) {
            bos.write(len);
          }
          byte[] data = bos.toByteArray();
          return defineClass(name, data, 0, data.length);
        } catch (IOException e) {
          e.printStackTrace();
        }
        return super.findClass(name);
      }
     
      // 获取要加载 的class文件名
      private String getFileName(String name) {
        int index = name.lastIndexOf(".");
        if (index > 0) {
          return name.substring(index + 1) + ".class";
        } else {
          return name + ".class";
        }
      }
     
      private Class<?> loadClassFromJarOrZip(String className)
          throws MalformedURLException, ClassNotFoundException {
        File file = new File(libPath);
        URL url = file.toURI().toURL();
        URLClassLoader classLoader = null;
        try {
          classLoader =
              new URLClassLoader(new URL[] {url}, Thread.currentThread().getContextClassLoader());
          return classLoader.loadClass(className);
        } finally {
          if (classLoader != null) {
            try {
              classLoader.close();
            } catch (IOException e) {
              // pass
            }
          }
        }
      }
    }
    package com.mp.util;
     
    import java.lang.reflect.Method;
     
    public class ClassLoaderTest {
      public static void main(String[] args) throws ClassNotFoundException {
        System.out.println("使用目录加载class");
        call("/tmp/t1", "basic.javastd.HelloWorld", "printVersion");
        call("/tmp/t2", "basic.javastd.HelloWorld", "printVersion");
        System.out.println("使用jar加载class");
        call("/tmp/t1/javastd-0.0.1-SNAPSHOT.jar", "basic.javastd.HelloWorld", "printVersion");
        call("/tmp/t2/javastd-0.0.1-SNAPSHOT.jar", "basic.javastd.HelloWorld", "printVersion");
      }
     
      public static void call(String classFilePath, String className, String methodName) {
        ClassLoader loader = new MyClassloader(classFilePath);
        try {
          Class<?> loadClass = loader.loadClass(className);
          Method declaredMethod = loadClass.getDeclaredMethod(methodName);
          declaredMethod.invoke(loadClass.newInstance());
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

    输出:

    使用目录加载class

    v1 static code

    version 1

    v2 static code

    version 2

    使用jar加载class

    v1 static code

    version 1

    v2 static code

    version 2

    展开全文
  • 当一个项目使用的jar包较多时,代码经常在运行的时候抛出异常:java.lang.NoSuchMethodException,java.lang.ClassNotFoundException,基本是存在多个jar包包含相同class类文件导致的,运行期引用的class由于版本...
  • 3、这时候 out 路径下 会一个 一模一样的 class 文件 这个文件是修改以后的文件 再将 main 方法去掉 后 再 执行 Build Project 4、执行 src 下的 TEST.java 类 (test.java 根据 需要配置参数几个) 会在 out 下 ...
  • 修改jar包中class文件

    千次阅读 2020-04-02 00:29:22
    需求:银行跑批任务执行时要调用行方自己的短信平台给科技部人员发送短信,行方提供一个jar文件,通过shell脚本传参调用即可。 问题点:shell脚本调用jar包没太大问题,关键在于,需要在jar...替换class文件—&g...

    需求:银行跑批任务执行时要调用行方自己的短信平台给科技部人员发送短信,行方提供一个jar文件,通过shell脚本传参调用即可。

    问题点:shell脚本调用jar包没太大问题,关键在于,需要在jar包中的某个类中配置短信平台的用户名、密码。

    解决方案:将jar反编译—>保存为.java文件—>修改文件内容—>重新编译—>将原来jar包解压—>替换class文件—>压缩为jar包。


    是时候表演真正的技术啦!


    首先,看一下我的msg.jar包的结构,直接解压是这样式的~

    我要修改的代码就是这个T.class,但是class文件没办法直接修改

    所以我们需要反编译工具,我使用的是jd-gui。

    链接:https://pan.baidu.com/s/1qP4N8Uvss8lRbWp_1h91Fg 
    提取码:i6mk

    打开后:

    反编译还是没办法直接修改的,Ctrl+S将其保存为.java文件

    保存之后就可以通过编辑工具进行修改了,因为我的这个类是依赖了其他很多类的,修改完直接javac编译该文件会报错

    所以,我们要建一个项目,为这个java文件配置相同的目录结构,把这个类所依赖的jar包(其实就是本jar包,但是要先解压,然后把该类的class文件删掉,再压缩为jar文件即可,压缩为jar包的方式见后边)导入,将项目打成jar包,再将jar包解压,将修改的类的class文件拿出来就可以了。

    为了简便,我用idea直接建了一个spring boot项目,

    因为我要改的class文件就在jar包根目录下,所以我直接保存后的java文件放到启动类同目录就行了,如果不是的话,根据class文件所在jar包的目录结构在项目中创建对应目录结构即可。

    这时候,其实是会报错的,因为依赖的很多类都没有,但我已经引入jar包了,所以不会报错。

    引入剔除该class文件的jar包

     

    还有修改一下jdk之类的操作不细说了,pom文件加一下本地jar包依赖、jdk版本、和编译打包的一些依赖配置。

    <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <dependency>
                <groupId>com.jugan.util</groupId>
                <artifactId>com.jugan.util</artifactId>
                <version>1.0</version>
                <scope>system</scope>
                <systemPath>${project.basedir}/lib/msg.jar</systemPath>
            </dependency>
        </dependencies>
    
        <build>
    
            <resources>
                <resource>
                    <directory>lib</directory>
    <!--                <targetPath>BOOT-INF/lib/</targetPath>-->
                    <includes>
                        <include>F:/workspace/msg/lib/msg.jar</include>
                    </includes>
                </resource>
            </resources>
    
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>

    然后,修改代码

    maven 编译打包

    编译打包成功,去把打好的jar包中的class文件拿出来,替换掉原始jar包中的class文件,

    然后将其压缩为jar包。

    注意,在解压缩的jar包的文件夹里边选中所有文件进行压缩,直接压缩文件夹的话,会多出一层。

    大功告成。

     

     

    展开全文
  • 与实现方式不同,语法相同,但是我们在desc“ Lcom / dex2jar \ t \ u1234;”类型中支持转义。 其他工具: 用法 sh d2j-dex2jar.sh -f〜/ path / to / apk_to_decompile.apk 输出文件将是apk_to_decompile-dex2...
  • 首先使用sftp工具把class文件传到jar包所在目录,然后linux下替换jar包里面的class文件总共分为4步: (1)使用jar tvf jar名称 | grep 目标文件名 查询出目标文件在war包中的目录 jar tvf cbam-monitor-task-0.0.1-...

    首先使用sftp工具把class文件传到jar包所在目录,然后Linux下替换jar包里面的class文件总共分为4步:

    (1)使用jar tvf jar名称 | grep 目标文件名 查询出目标文件在war包中的目录

    jar tvf cbam-monitor-task-0.0.1-SNAPSHOT.jar | grep LinuxSystemOperateServiceImpl.class
    

    (2)使用jar xvf jar名称 目标文件名(copy上面查出的全路径) 将目标文件及所在war包中的目录解压到当前路径

    jar -xvf cbam-monitor-task-0.0.1-SNAPSHOT.jar BOOT-INF/classes/com/cuai/cbam/monitor/service/impl/LinuxSystemOperateServiceImpl.class
    

    (3)修改目标文件的内容,或者将要新的目标文件替换掉提取出来的目标文件

    cp LinuxSystemOperateServiceImpl.class BOOT-INF/classes/com/cuai/cbam/monitor/service/impl/LinuxSystemOperateServiceImpl.class
    

    (4)使用jar uvf jar名称 目标文件名(和步骤(2)中的目标文件名相同) 将新目标文件替换到 jar包中

    jar -uvf cbam-monitor-task-0.0.1-SNAPSHOT.jar BOOT-INF/classes/com/cuai/cbam/monitor/service/impl/LinuxSystemOperateServiceImpl.class
    

    上面4步的操作截图如下:
    在这里插入图片描述

    注:如果只是改配置文件直接vim命令打开jar包然后命令行模式输入/application.yml搜索文件名,然后按enter键进入文件,编辑后输入:wq保存即可。

    展开全文
  • 做个记录,在工作中遇到了Maven引入两个jar包下路径相同的类,一个是org.slf4j包下的logger,一个是phoenix-5.0.0-HBase-2.0-client.jar包下的logger,路径都是org.xxxx。 我想用的是slf4j的,但是import中不知道...
  • Jar包中Class文件替换

    千次阅读 2020-08-05 15:09:58
    说明:本文是已经对java文件进行编译了之后,已经形成了class文件,在这里只涉及用class文件直接替换jar包里面的class文件 Ps: 至于如何拿出jar包的class文件,反编译修改改文件后又重新编译,再放入原文件重新打jar...
  • 之前碰到一个疑虑,客户生产环境里面jar包里面的class文件和src 路径下 编译出来的class 相同(包名,类名,里面的逻辑不同), 但偏偏在客户那里正常跑了3个月(tomcat),于是自己写了个demo public class ...
  • 修改jar包中class文件的内容

    千次阅读 2020-08-06 17:19:43
    4、把新的class文件,替换jar包中的旧class文件,就可以了。 实际演示 例如:我想要修改mysql驱动包mysql-connector-java-6.0.6.jar中maxAllowPacket的默认值。 1、使用jad打开jar包,先找到class文件...
  • linux下替换jar包里面的class文件

    千次阅读 2020-05-29 16:08:29
    linux相应目录下:zcsfastDFSTest-0.0.1-SNAPSHOT.jar 步骤如下: 如果要替换的文件在jar包的二级及以下目录下,则需要以下步骤: (1)使用jar tvf jar名称 | grep 目标文件名 查询出目标文件在war包中的目录 ...
  • 以下是代码实验public class Test { public static void main(String[] args) throws Exception{ //当前Test类所在目录(包)的a.txt System.out.println(Test.class.getResource("a.txt")); //当前项目的根目录的a....
  • IDEA将项目打包为指定class文件的jar

    千次阅读 2019-01-30 10:12:03
    【背景】  公司最近要和某大公司合作... 这个单独验证的服务需要以jar的形式嵌入到服务中,其中为了避免jar包的版本冲突问题,所以需要将校验服务打包为只包含本项目中对应class文件的jar(不包含任何maven依赖的j...
  • 两个不同jar包下相同文件的获取: 1、创建3个工程(test,test2 ,testDemo)  test和test2 资源目录下有相同的配置文件(/META/prop.properties)  testDemo 为获取配置文件的工程; testDemo代码: ...
  • public class Hello{ public void sayHello(){ System.out.println("Hello"); } } public class Demo{ public static void main(String[] args) { Hello Hello = new Hello(); Hello.sayHello(); } } 同...
  • smali/baksmali 的不同实现,相同的语法,但我们支持类型 desc "Lcom/dex2jar\t\u1234;" 的转义 dex-writer [待发布]以与 dex-reader 相同的方式编写 dex。 寻求帮助 请发送电子邮件至 dex2jar@googlegroups.com 或...
  • 这里所说的冲突,是指类的包名和类型完全相同的时候希望同时使用相同类的不同版本)。 参考地址:https://baijiahao.baidu.com/s?id=1636309817155065432&wfr=spider&for=pc 处理思路:见上图,使用...
  • 两个jar包下相同包名类名引入冲突

    万次阅读 2018-11-03 18:06:27
    时候引入的jar包中的包名类名与其他jar包中的包名类名相同,导致程序在编译或运行的时候无法正确引用想要的类,现有一种解决方法就是去掉其中不需要的那个jar一个项目下需要用到OpenCV和javacv,但是javacv...
  • 【Java】jar包中 类名相同

    千次阅读 2018-12-09 19:08:39
    如果类路径下两个全限定名完全相同的类,而且另一个类import了这个全限定名,会怎么样? 下面验证下: import com.liyao.lib.Util; public class Main{ public static void main(String args[]){ System.out...
  • 最近在开发一个SpringBoot项目的时候,自己写了组件,以打成Jar包的形式引入到SpringBoot项目中使用,而组件中一块是根据classname去根据Spring上下文ApplicationContext对象获取SpringBoot项目中注入好的Bean,...
  • 这个博客的由来 在大约一个月前,我的leader收到了一个来自之前项目...项目存在两个有相同类的jar包会发生什么 首先不会炸,我也自己试验了一下,如下: 看图有点枯燥么,上代码!!! public class Test { pub
  • java同时引用不同版本同一个jar

    千次阅读 2021-10-23 15:11:17
    java是当类名包名相同且类加载器相同时认为是同一个类,想要同时使用不同版本jar包只能通过自定义类加载器,破坏双亲委派模型来实现。 一 、Java类加载的过程 Java代码从编码完成到运行,包含两个步骤: 编译:把写...
  • 在引入的连个jar中,有相同类路径,类名的类 在pom文件中,按照这样的顺序引入 这两个jar中,都 SearchGoodVo 这个类,并且类路径相同 suning-common 多了个 private String[] codeMerchantArr; 属性 ...
  • ■前言 使用Jenkins自动打包,生成jar... (只有一个class文件是不同的,其余的class文件都相同) ■原因 JDK的小版本不同 ■详细 使用的JDK都是java 8, 大版本是相同的,小版本不同 ・①Jenkins所...
  • Java| 命令行运行Java程序(JarClass)

    万次阅读 2018-04-26 20:38:52
    在前面的文章中,我们已经知道如何使用javac来编译java文件和运行简单的单个class文件了,命令行编译Java...直接使用java -jar yveshe.jar的方式来运行,这里在yveshe.jar中的项目清单文件MANIFEST.MF需要配置Main-Class
  • IDEA打包Java的class文件为jar

    千次阅读 2019-12-30 19:02:29
    文章目录IDEA打包Java的class文件为jar包打开Project Structure---->>>Artifacts然后新建Directory,注意这个目录一定与对应的java文件中的包名相同然后在新建的文件目录下添加对应的class文件,在电机OK...
  • 当项目中你指定的jar包,但是其他引进的依赖中也可能包含这个jar包,由于版本对不上可能会导致项目出问题 例如:一个gson中一个jar包中的JsonObject文件中没有keySet() ## Failed to execute plan for region...
  • 【转】java class生成jar

    千次阅读 2017-10-19 22:41:33
    进入dos操作符窗口cd进入要打成jar包的class文件所有文件夹目录jar cvf [生成jar的名称.jar] [列出class文件] //若多个,以空隔隔开如:一。操作零散的单个或几个class文件jar cvf ibstool.jar ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 171,143
精华内容 68,457
关键字:

不同jar有相同class