自定义类加载器(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013219624/article/details/89256950

1.自定义类加载器的作用
其实就是对已经加密的class解密,再加载到虚拟机中

2.生成加密的class文件

  1. 被加密的java文件

    public interface IUserDao {
        void save();
    }
    public class UserDao implements IUserDao {
        @Override
        public void save() {
            System.out.print("save method.");
        }
    }
    
  2. 加密工具类

    public final class DesUtils {
        private static final String DES = "DES";
        private static final String KEY = "4YztMHI7PsT4rLZN";
    
        private DesUtils() {}
    
        public static byte[] encode(byte[] bytes) {
            try {
                return encrypt(bytes, KEY.getBytes());
            } catch (Exception e) {
                throw new RuntimeException("encode bytes error.");
            }
        }
    
        public static byte[] decode(byte[] bytes) {
            try {
                return decrypt(bytes, KEY.getBytes());
            } catch (Exception e) {
                throw new RuntimeException("decode bytes error.");
            }
        }
    
        private static byte[] encrypt(byte[] src, byte[] key) throws Exception {
            SecureRandom sr = new SecureRandom();
            DESKeySpec dks = new DESKeySpec(key);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(DES);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);
            return cipher.doFinal(src);
        }
    
        private static byte[] decrypt(byte[] src, byte[] key) throws Exception {
            SecureRandom sr = new SecureRandom();
            DESKeySpec dks = new DESKeySpec(key);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(DES);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);
            return cipher.doFinal(src);
        }
    
        private static String byte2hex(byte[] b) {
            StringBuilder hs = new StringBuilder();
            String temp;
            for (int n = 0; n < b.length; n++) {
                temp = (Integer.toHexString(b[n] & 0XFF));
                if (temp.length() == 1) {
                    hs.append("0").append(temp);
                } else {
                    hs.append(temp);
                }
            }
            return hs.toString().toUpperCase();
    
        }
    
        private static byte[] hex2byte(byte[] b) {
            if ((b.length % 2) != 0) {
                throw new IllegalArgumentException("length not even");
            }
            byte[] b2 = new byte[b.length / 2];
            for (int n = 0; n < b.length; n += 2) {
                String item = new String(b, n, 2);
                b2[n / 2] = (byte) Integer.parseInt(item, 16);
            }
            return b2;
        }
    }
    
  3. 生成加密class文件

    public static void createEncodeFile() {
        String targetFilePath = "D:\\test\\target\\classes\\test\\UserDao.class";
        String encodedFilePath = "D:\\test\\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;
            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) {}
            }
        }
    }
    

3.自定义类加载器

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();
            }
        }
    }
}

4.测试

public static void main(String[] args) throws Exception {
    EncodeClassLoader classLoader = new EncodeClassLoader();
    String filePath = "D:\\test\\";
    String name = "test.UserDao";
    try {
        Class<IUserDao> userDaoClass = (Class<IUserDao>) classLoader.findClassByFilePathAndName(filePath, name);
        IUserDao userDao = userDaoClass.newInstance();
        userDao.save();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

猜你喜欢

转载自blog.csdn.net/u013219624/article/details/89256950