美文网首页
加密的.class文件,加载使用之

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

作者: jsjack_wang | 来源:发表于2018-01-31 19:52 被阅读0次

    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

    相关文章

      网友评论

          本文标题:加密的.class文件,加载使用之

          本文链接:https://www.haomeiwen.com/subject/kcilzxtx.html