使用javassist修改.class文件,并重新打包

Javassist是一款字节码编辑工具,可以直接编辑和生成Java生成的字节码,以达到对.class文件进行动态修改的效果。熟练使用这套工具,可以让Java编程更接近与动态语言编程。

下面实现如何修改jar包里的方法

Javassist下载地址 查看

1.准备jar包

my/Solution.java

  1. package my.tools;
  2. public class Solution{
  3.  
  4. public int lengthOfLongestSubstring(String s) {
  5. int longSub = 0;
  6. if(s.isEmpty()) return 0;
  7. if(s.length()==1) return 1;
  8. char[] arr = s.toCharArray();
  9. String str = String.valueOf(arr[0]);
  10. longSub = 1;
  11. for(int i=1;i<s.length();i++){
  12. int pos = str.indexOf(arr[i]);
  13. if (pos !=-1) {
  14. str = str.substring(pos+1)+arr[i];
  15. }else{
  16. str+=arr[i];
  17. }
  18. if(str.length()>longSub) longSub = str.length();
  19. }
  20. return longSub;
  21. }
  22.  
  23. public int strStr(String haystack, String needle) {
  24.  
  25. if(needle.isEmpty()||needle.equals(haystack)) return 0;
  26. int l=needle.length();
  27. int r = haystack.length()-l;
  28. for(int i=0;i<r+1;i++){
  29. String tempStr=haystack.substring(i,l+i);
  30. if(tempStr.equals(needle))
  31. return i;
  32. }
  33. return -1;
  34. }
  35.  
  36. }

my/Encrypt.java

  1. package my.tools;
  2. import javax.crypto.Cipher;
  3. import javax.crypto.SecretKey;
  4. import javax.crypto.SecretKeyFactory;
  5. import javax.crypto.spec.DESKeySpec;
  6. import javax.crypto.spec.IvParameterSpec;
  7. import java.math.BigInteger;
  8. import java.net.URLDecoder;
  9. import java.security.MessageDigest;
  10. import java.security.NoSuchAlgorithmException;
  11.  
  12. public class Encrypt {
  13. public static String md5(String plainText) {
  14. byte[] secretBytes = null;
  15. try {
  16. MessageDigest md = MessageDigest.getInstance("MD5");
  17. md.update(plainText.getBytes());
  18. secretBytes = md.digest();
  19. } catch (NoSuchAlgorithmException e) {
  20. throw new RuntimeException("dont have algorithm");
  21. }
  22.  
  23. String md5code = new BigInteger(1, secretBytes).toString(16);
  24.  
  25. for (int i = 0; i < 32 - md5code.length(); i++) {
  26. md5code = "0" + md5code;
  27. }
  28. return md5code;
  29. }
  30.  
  31. public static String decrypt(String message, String key) throws Exception {
  32. byte[] bytesrc = convertHexString(message);
  33. Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
  34. DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
  35. SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  36. SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
  37. IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
  38.  
  39. cipher.init(2, secretKey, iv);
  40.  
  41. byte[] retByte = cipher.doFinal(bytesrc);
  42. return new String(retByte);
  43. }
  44.  
  45. public static byte[] convertHexString(String ss) {
  46. byte[] digest = new byte[ss.length() / 2];
  47. for (int i = 0; i < digest.length; i++) {
  48. String byteString = ss.substring(2 * i, 2 * i + 2);
  49. int byteValue = Integer.parseInt(byteString, 16);
  50. digest[i] = ((byte) byteValue);
  51. }
  52. return digest;
  53. }
  54.  
  55. public static String decode(String value) {
  56. try {
  57. return URLDecoder.decode(decrypt(value, "Yst@2_BI"), "utf-8");
  58. } catch (Exception e) {
  59. e.printStackTrace();
  60. }
  61. return null;
  62. }
  63. }

新建resource

编译 javac  -sourcepath my my\tools\*.java -d resource

META-INF/MANIFEST.MF

  1. Manifest-Version: 1.0
  2. Created-By: 1.8.0_151 (Oracle Corporation)

进入resource打包  jar -cvfm mytools.jar META-INF\MANIFEST.MF *

使用

  1. import my.tools.Solution;
  2.  
  3. public class Main {
  4.  
  5. public static void main(String[] args) {
  6.  
  7. System.out.println(new Solution().strStr("aacabseew", "ab"));
  8. }
  9. }

输出:3

实现的查找第二个字符串出现的位置

2.修改编译后的class

导入下载的Javassist里的javassist.jar

  1. import javassist.ClassPool;
  2. import javassist.CtClass;
  3. import javassist.CtMethod;
  4.  
  5. public class Main {
  6.  
  7. public static void main(String[] args) {
  8.  
  9. try {
  10. ClassPool.getDefault().insertClassPath("data/mytools.jar");
  11. CtClass c2 = ClassPool.getDefault().getCtClass("my.tools.Solution");
  12. CtMethod[] ms = c2.getDeclaredMethods();
  13. for (CtMethod c : ms) {
  14. System.out.println(c.getName());
  15. CtClass[] ps = c.getParameterTypes();
  16. for (CtClass cx : ps) {
  17. System.out.println("\t" + cx.getName());
  18. }
  19. if (c.getName().equals("strStr") && ps.length == 2
  20. && ps[0].getName().equals("java.lang.String")
  21. && ps[1].getName().equals("java.lang.String")) {
  22. c.setBody("{System.out.println($1);return 0;}");
  23. }
  24. }
  25. c2.writeFile();
  26.  
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }

运行后会在项目根目录下生成修改后的class文件

3.生成新的jar

将以前的jar包修改mytools.zip

解压mytools.zip为mytools1,将刚才生成的my/tools/Solution.class替换掉mytools1里的Solution.class,

压缩mytools1为mytools1.zip

修改文件名为mytools1.jar

导入新的jar包

测试

  1. import my.tools.Solution;
  2.  
  3. public class Main {
  4.  
  5. public static void main(String[] args) {
  6.  
  7. System.out.println(new Solution().strStr("aacabseew","ab"));
  8.  
  9. }
  10. }

输出

aacabseew
0

完成

修改jar的.class文件,并重新打包的更多相关文章

  1. linux下修改jar中的文件

    解压修改后再打包 解压: jar xvf xxx.jar 打包: jar cvfm0 xxx.jar META-INF/MANIFEST.MF ./ 注: -m参数可以将 一个具体的mainfest文 ...

  2. Java实现动态修改Jar包内文件内容

    import java.io.*; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; ...

  3. Java 操作jar包工具类以及如何快速修改Jar包里的文件内容

    需求背景:写了一个实时读取日志文件以及监控的小程序,打包成了Jar包可执行文件,通过我们的web主系统上传到各个服务器,然后调用ssh命令执行.每次上传前都要通过解压缩软件修改或者替换里面的配置文件, ...

  4. Java如何快速修改Jar包里的文件内容

    需求背景:写了一个实时读取日志文件以及监控的小程序,打包成了Jar包可执行文件,通过我们的web主系统上传到各个服务器,然后调用ssh命令执行.每次上传前都要通过解压缩软件修改或者替换里面的配置文件, ...

  5. Android 编程下如何修改 jar 文件的包名

    首先我们要说说为什么要修改 jar 文件的包名,jar 包我们会非常高频率的使用,尤其是用一些其他三方库的时候,往往把 java 代码打包成 jar 文件,方便项目依赖使用.笔者在开发过程中遇到过一些 ...

  6. 修改jar中的class文件

    在工作中有可能会遇到需要修改jar的情况.正常情况下,如果有源代码的话,就比较容易,直接修改源代码,再导出新的jar文件即可.但是如果没有源代码就比较麻烦了,下面记录了没有源代码的情况修改jar的方法 ...

  7. 曹工杂谈:Linux服务器上,Spring Boot 原地修改 jar 包配置文件/替换class文件,免去重复上传的麻烦

    一.前言 相信很多同学有这样的需求,现在很多公司都有多地的研发中心,经常需要跨地区部署,比如,博主人在成都,但是服务器是北京的.一般城市间网络都不怎么好,上传一个几十兆的jar包那是真的慢,别说现在微 ...

  8. 修改jar包配置文件的正确操作,jar包解压出来的文件夹重新打成jar,不依靠开发工具!!!!

    修改jar包配置文件的正确操作,有的时候通过一些解压工具可以对内部的文件进行修改,但是有时候会无效.这就很烦了 一.背景:       有一个springboot项目,事先我已经用编译好打成jar包以 ...

  9. 使用fat jar和exe4j把java程序打包成exe执行文件---转载的

    java应用编写测试好之后都是jar包或class文件,客户拿到这个东西后一般是不会java开发者那样在命令窗口下面输入运行的.客户要求的就是直接点击应用名称运行.java在方面做得很不友好,开发人员 ...

随机推荐

  1. 项目Alpha冲刺(团队)-第七天冲刺

    格式描述 课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(团队) 团队名称:为了交项目干杯 作业目标:描述第七天冲刺的项目进展.问题困难.心得体会 队员姓名与学号 队员学号 ...

  2. 11.vue-router编程式导航

    页面导航的两种方式 声明式导航:通过点击链接实现导航的方式,叫做声明式导航 例如:普通网页中的链接或vue中的 编程式导航:通过调用JavaScrip形式的API实现导航的方式,叫做编程式导航 例如: ...

  3. 六.深浅copy

    先问问大家,什么是拷贝?拷贝是音译的词,其实他是从copy这个英文单词音译过来的,那什么是copy? copy其实就是复制一份,也就是所谓的抄一份.深浅copy其实就是完全复制一份,和部分复制一份的意 ...

  4. fitnesse wiki界面设置变量

    有时候我们可能多组测试数据会到同一个值,这样我们就可以设置一个变量,修改时只需要修改一个地方即可,而不需要对每组测试数据的这列数据进行修改 如下图: (1)定义变量:!define A {10}  , ...

  5. vue中代理实现方法

    vue中代理实现方法如下: const path = require('path'); function resolve(dir) { return path.join(__dirname, dir) ...

  6. 通过redash query results 数据源实现跨数据库的查询

    redash 提供了一个简单的 query results 可以帮助我们进行跨数据源的查询处理 底层数据的存储是基于sqlite的,期望后期有调整(毕竟处理能力有限),同时 query results ...

  7. 【loj3059】【hnoi2019】序列

    题目 给出一个长度为 \(n\) 的序列 \(A\) ; 你需要构造一个新的序列\(B\) ,满足: $B_{i} \le B_{i+1} (1 \le i \lt n ) $ $\sum_{i=1} ...

  8. 53、Spark Streaming:输入DStream之Kafka数据源实战

    一.基于Receiver的方式 1.概述 基于Receiver的方式: Receiver是使用Kafka的高层次Consumer API来实现的.receiver从Kafka中获取的数据都是存储在Sp ...

  9. 转载:理解scala中的Symbol

    相信很多人和我一样,在刚接触Scala时,会觉得Symbol类型很奇怪,既然Scala中字符串都是不可变的,那么Symbol类型到底有什么作用呢? 简单来说,相比较于String类型,Symbol类型 ...

  10. GoCN每日新闻(2019-10-01)

    GoCN每日新闻(2019-10-01) GoCN每日新闻(2019-10-01) 1. 我依然爱着 GOPATH https://divan.dev/posts/gopath/ 2. Go 代码注释 ...