package st.gravel.support.compiler; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; public class StClassLoader extends ClassLoader { private static class ClassRecord { private final String name; public String getName() { return name; } public Class<?> getStClass() { return stClass; } public String getChecksum() { return checksum; } private final Class<?> stClass; private final String checksum; public ClassRecord(String name, Class<?> stClass, String checksum) { this.name = name; this.stClass = stClass; this.checksum = checksum; } } private final HashMap<String, StClassLoader.ClassRecord> stClasses = new HashMap<>(); public Class<?> defineClass(final String name, final byte[] b) { final StClassLoader.ClassRecord current = stClasses.get(name); if (current == null) { final Class<?> newClass = defineClass(name, b, 0, b.length); String checksum = sha256Hash(b); stClasses.put(name, new ClassRecord(name, newClass, checksum)); return newClass; } else { String checksum = sha256Hash(b); if (!current.getChecksum().equals(checksum)) { throw new ClassRedefinitionError(); } return current.getStClass(); } } public static String sha256Hash(final byte[] b) { MessageDigest md; try { md = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } md.update(b); byte[] mdbytes = md.digest(); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < mdbytes.length; i++) { hexString.append(Integer.toHexString(0xFF & mdbytes[i])); } String checksum = hexString.toString(); return checksum; } }