0x01 前言

想获取某个类的class字节码那么我们可以使用此方法

  1. # 目录结构
  2. ├── ClassLoader
  3. └── CustomClassLoaderAddClassFile
  4. ├── Test.java (用来做测试的方法)
  5. ├── ClassByte.java (用来获取类的字节码的)
  6. ├── ClTestClass.class (一个编译好的类文件,用来被获取字节码用的)

0x02 ClassByte (用来获取类的字节码的)

  1. package ClassLoader.CustomClassLoaderAddClassFile;
  2. import java.io.IOException;
  3. import java.net.URI;
  4. import java.net.URISyntaxException;
  5. import java.nio.file.Files;
  6. import java.nio.file.Path;
  7. import java.nio.file.Paths;
  8. import java.util.Arrays;
  9. public class ClassByte {
  10. public String getFileByte(String filePath) {
  11. byte[] classBytes = null;
  12. Path path = null;
  13. try {
  14. path = Paths.get(new URI(filePath));
  15. classBytes = Files.readAllBytes(path);
  16. } catch (IOException | URISyntaxException e) {
  17. e.printStackTrace();
  18. }
  19. // 返回类字节码
  20. return Arrays.toString(classBytes);
  21. }
  22. }

0x03 ClTestClass.class (用来被获取字节码用的)

  1. // 未编译前的源码
  2. package ClassLoader.CustomClassLoaderAddClassFile;
  3. public class ClTestClass {
  4. public void show() {
  5. System.out.println("show test!");
  6. }
  7. }

编译后的
ClTestClass.class.zip

0x04 例子

0x04.1 例子: 获取某个类字节码

  1. // 例子: 获取 ClTestClass.class 类的字节码
  2. // 注意: 要编译过的才能获取
  3. // /Users/pmiaowu/Desktop/ClTestClass.class 这个路径 取决与你把 ClTestClass.class放那里
  4. package ClassLoader.CustomClassLoaderAddClassFile;
  5. public class Test {
  6. public static void main(String[] args) {
  7. String cPath = "file:///Users/pmiaowu/Desktop/ClTestClass.class";
  8. ClassByte cbs = new ClassByte();
  9. System.out.println(cbs.getFileByte(cPath));
  10. }
  11. }
  12. // 执行结果
  13. [-54, -2, -70, -66, 0, 0, 0, 51, 0, 31, 10, 0, 6, 0, 17, 9, 0, 18, 0, 19, 8, 0, 20, 10, 0, 21, 0, 22, 7, 0, 23, 7, 0, 24, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 18, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 97, 98, 108, 101, 1, 0, 4, 116, 104, 105, 115, 1, 0, 55, 76, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 47, 67, 117, 115, 116, 111, 109, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 65, 100, 100, 67, 108, 97, 115, 115, 70, 105, 108, 101, 47, 67, 108, 84, 101, 115, 116, 67, 108, 97, 115, 115, 59, 1, 0, 4, 115, 104, 111, 119, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 16, 67, 108, 84, 101, 115, 116, 67, 108, 97, 115, 115, 46, 106, 97, 118, 97, 12, 0, 7, 0, 8, 7, 0, 25, 12, 0, 26, 0, 27, 1, 0, 10, 115, 104, 111, 119, 32, 116, 101, 115, 116, 33, 7, 0, 28, 12, 0, 29, 0, 30, 1, 0, 53, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 47, 67, 117, 115, 116, 111, 109, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 65, 100, 100, 67, 108, 97, 115, 115, 70, 105, 108, 101, 47, 67, 108, 84, 101, 115, 116, 67, 108, 97, 115, 115, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 121, 115, 116, 101, 109, 1, 0, 3, 111, 117, 116, 1, 0, 21, 76, 106, 97, 118, 97, 47, 105, 111, 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 59, 1, 0, 19, 106, 97, 118, 97, 47, 105, 111, 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 1, 0, 7, 112, 114, 105, 110, 116, 108, 110, 1, 0, 21, 40, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 41, 86, 0, 33, 0, 5, 0, 6, 0, 0, 0, 0, 0, 2, 0, 1, 0, 7, 0, 8, 0, 1, 0, 9, 0, 0, 0, 47, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 2, 0, 10, 0, 0, 0, 6, 0, 1, 0, 0, 0, 3, 0, 11, 0, 0, 0, 12, 0, 1, 0, 0, 0, 5, 0, 12, 0, 13, 0, 0, 0, 1, 0, 14, 0, 8, 0, 1, 0, 9, 0, 0, 0, 55, 0, 2, 0, 1, 0, 0, 0, 9, -78, 0, 2, 18, 3, -74, 0, 4, -79, 0, 0, 0, 2, 0, 10, 0, 0, 0, 10, 0, 2, 0, 0, 0, 5, 0, 8, 0, 6, 0, 11, 0, 0, 0, 12, 0, 1, 0, 0, 0, 9, 0, 12, 0, 13, 0, 0, 0, 1, 0, 15, 0, 0, 0, 2, 0, 16]

0x04.2 使用的类字节码并反射调用方法

  1. // 例子: 使用ClTestClass类的字节码进行实例化并反射调用show方法
  2. package ClassLoader.CustomClassLoaderAddClassFile;
  3. import java.lang.reflect.Method;
  4. public class Test {
  5. public static void main(String[] args) {
  6. // loadClassName = ClTestClass.class类,源码里面写的 package路径+被调用类的类名称
  7. String loadClassName = "ClassLoader.CustomClassLoaderAddClassFile.ClTestClass";
  8. // ClTestClass.class类的字节码
  9. byte[] classBytes = new byte[]{
  10. -54, -2, -70, -66, 0, 0, 0, 51, 0, 31, 10, 0, 6, 0, 17, 9, 0, 18, 0, 19, 8, 0, 20, 10, 0, 21, 0, 22, 7, 0, 23, 7, 0, 24, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 18, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 97, 98, 108, 101, 1, 0, 4, 116, 104, 105, 115, 1, 0, 55, 76, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 47, 67, 117, 115, 116, 111, 109, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 65, 100, 100, 67, 108, 97, 115, 115, 70, 105, 108, 101, 47, 67, 108, 84, 101, 115, 116, 67, 108, 97, 115, 115, 59, 1, 0, 4, 115, 104, 111, 119, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 16, 67, 108, 84, 101, 115, 116, 67, 108, 97, 115, 115, 46, 106, 97, 118, 97, 12, 0, 7, 0, 8, 7, 0, 25, 12, 0, 26, 0, 27, 1, 0, 10, 115, 104, 111, 119, 32, 116, 101, 115, 116, 33, 7, 0, 28, 12, 0, 29, 0, 30, 1, 0, 53, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 47, 67, 117, 115, 116, 111, 109, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114, 65, 100, 100, 67, 108, 97, 115, 115, 70, 105, 108, 101, 47, 67, 108, 84, 101, 115, 116, 67, 108, 97, 115, 115, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 121, 115, 116, 101, 109, 1, 0, 3, 111, 117, 116, 1, 0, 21, 76, 106, 97, 118, 97, 47, 105, 111, 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 59, 1, 0, 19, 106, 97, 118, 97, 47, 105, 111, 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 1, 0, 7, 112, 114, 105, 110, 116, 108, 110, 1, 0, 21, 40, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 41, 86, 0, 33, 0, 5, 0, 6, 0, 0, 0, 0, 0, 2, 0, 1, 0, 7, 0, 8, 0, 1, 0, 9, 0, 0, 0, 47, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 2, 0, 10, 0, 0, 0, 6, 0, 1, 0, 0, 0, 3, 0, 11, 0, 0, 0, 12, 0, 1, 0, 0, 0, 5, 0, 12, 0, 13, 0, 0, 0, 1, 0, 14, 0, 8, 0, 1, 0, 9, 0, 0, 0, 55, 0, 2, 0, 1, 0, 0, 0, 9, -78, 0, 2, 18, 3, -74, 0, 4, -79, 0, 0, 0, 2, 0, 10, 0, 0, 0, 10, 0, 2, 0, 0, 0, 5, 0, 8, 0, 6, 0, 11, 0, 0, 0, 12, 0, 1, 0, 0, 0, 9, 0, 12, 0, 13, 0, 0, 0, 1, 0, 15, 0, 0, 0, 2, 0, 16
  11. };
  12. ByteClassLoader loader = new ByteClassLoader(loadClassName, classBytes);
  13. try {
  14. // 加载类
  15. Class testClass = loader.loadClass(loadClassName);
  16. // 实例化
  17. Object testInstance = testClass.newInstance();
  18. // 获取show方法
  19. Method method = testClass.getMethod("show");
  20. // 调用show方法
  21. method.invoke(testInstance);
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. // 运行结果
  28. show test!