加密的.class文件,加载使用之

1.简介

通过加密的.class文件,并将其加载到JVM中,然后再调用其方法。

2.小栗子源码

//生成的.class文件将要被加密
public class UserDao implements IUserDao {
    @Override
    public void save(User user) {
        System.out.print("save user.");
    }
}

// 生成加密的.class文件
@Test
public void createEncodeFile() {
    String targetFilePath = "C:\\MineProjects\\JavaDemo\\target\\classes\\com\\boomsecret\\classloader\\encode\\UserDao.class";
    String encodedFilePath = "C:\\MineProjects\\JavaDemo\\UserDao.class";
    FileInputStream fis = null;
    FileOutputStream fos = null;
    ByteArrayOutputStream baos = null;
    try {
        fis = new FileInputStream(new File(targetFilePath));
        fos = new FileOutputStream(new File(encodedFilePath));
        baos = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        int len = -1;
        while ((len = fis.read(bytes)) != -1) {
            baos.write(bytes, 0, len);
        }
        byte[] encode = DesUtils.encode(baos.toByteArray());
        fos.write(encode);
        fos.flush();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (Objects.nonNull(fis)) {
            try {
                fis.close();
            } catch (Exception e) {}
        }
        if (Objects.nonNull(fos)) {
            try {
                fos.close();
            } catch (Exception e) {}
        }
        if (Objects.nonNull(baos)) {
            try {
                baos.close();
            } catch (Exception e) {}
        }
    }
}

// 类加载器
public class EncodeClassLoader extends ClassLoader {
    private String filePath = null;

    protected Class<?> findClassByFilePathAndName(String filePath, String name)
            throws ClassNotFoundException {
        if (Objects.isNull(filePath) || Objects.isNull(name)) {
            throw new IllegalArgumentException("参数错误");
        }
        this.filePath = filePath;
        return findClass(name);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        StringBuilder stringBuilder = new StringBuilder(filePath)
                .append(name.substring(name.lastIndexOf(".") + 1))
                .append(".class");
        FileInputStream fis = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            fis = new FileInputStream(new File(stringBuilder.toString()));
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len = fis.read(bytes)) != -1) {
                baos.write(bytes, 0, len);
            }
            byte[] decodeBytes = DesUtils.decode(baos.toByteArray());
            return this.defineClass(name, decodeBytes, 0, decodeBytes.length);
        } catch (Exception e) {
            throw new ClassNotFoundException();
        } finally {
            closeStream(fis);
            closeStream(baos);
        }
    }

    private void closeStream(OutputStream stream) {
        if (Objects.nonNull(stream)) {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void closeStream(InputStream stream) {
        if (Objects.nonNull(stream)) {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.测试

@Test
public void loadEncodeFile() {
    EncodeClassLoader classLoader = new EncodeClassLoader();
    String filePath = "C:\\MineProjects\\JavaDemo\\";
    String name = "com.boomsecret.classloader.encode.UserDao";
    try {
        Class<IUserDao> userDaoClass = (Class<IUserDao>) classLoader.findClassByFilePathAndName(filePath, name);
        IUserDao userDao = userDaoClass.newInstance();
        userDao.save(new User());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
result:
    save user.

4.总结

像Android的热更新,应该用的类似的原理。总之,类加载器这一块还是有很多东西要看的。

源码地址:https://gitee.com/jsjack_wang/JavaDemo

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,130评论 25 709
  • 太长了,还是转载吧...今天在看博客的时候,无意中发现了@Trinea在GitHub上的一个项目Android开源...
    庞哈哈哈12138阅读 20,303评论 3 283
  • 晚饭的时候,旋转桌上的鸭蛋,手机闪光灯无意中发现,拍成了发光的蛋,有些惊喜。处理的时候用双重曝光来玩儿,很是喜欢。...
    非言阅读 191评论 0 0
  • 我非常喜欢逛淘宝,特别喜欢买几十块钱一件的衣服,基本不会超过50块,到最后越买越便宜,基本上保持在二三十一件。 ...
    榆木清清阅读 627评论 5 0
  • 这一年对于我来说是适应的一年。小学毕业我离别了我相处了六年的同学与1618相见。这里有66个新面孔他们成为了我的朋...
    青云邂阅读 184评论 0 0