refactor: rename modules

This commit is contained in:
ReaJason
2025-04-06 13:55:17 +08:00
parent 0f798b367f
commit e05d8ac106
27 changed files with 47 additions and 46 deletions
@@ -0,0 +1,53 @@
package com.reajason.javaweb.asm;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.SimpleRemapper;
/**
* @author ReaJason
* @since 2025/3/29
*/
public class ClassRenameUtils {
public static byte[] renameClass(byte[] classBytes, String newName) {
ClassReader reader = null;
try {
reader = new ClassReader(classBytes);
} catch (Exception e) {
throw new RuntimeException("invalid class bytes");
}
String oldClassName = reader.getClassName();
String newClassName = newName.replace('.', '/');
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
ClassRemapper adapter = new ClassRemapper(writer, new SimpleRemapper(oldClassName, newClassName));
reader.accept(adapter, 0);
return writer.toByteArray();
}
public static byte[] relocateClass(byte[] classBytes, String relocateClassPackage, String relocatePrefix) {
ClassReader reader = null;
try {
reader = new ClassReader(classBytes);
} catch (Exception e) {
throw new RuntimeException("invalid class bytes");
}
String oldClassName = relocateClassPackage.replace('.', '/');
String newClassName = relocatePrefix.replace('.', '/');
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
ClassRemapper adapter = new ClassRemapper(writer, new Remapper() {
@Override
public String map(String typeName) {
if (typeName.startsWith(oldClassName)) {
return typeName.replaceFirst(oldClassName, newClassName);
} else {
return typeName;
}
}
});
reader.accept(adapter, 0);
return writer.toByteArray();
}
}
@@ -0,0 +1,70 @@
package com.reajason.javaweb.asm;
import lombok.Getter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
public class InnerClassDiscovery {
/**
* Discovers all inner classes for a given class
*
* @param originalClass The class to discover inner classes for
* @return A set of fully qualified inner class names
*/
public static Set<String> findAllInnerClasses(Class<?> originalClass) throws IOException {
Set<String> innerClasses;
String resourceName = originalClass.getName().replace('.', '/') + ".class";
try (InputStream is = originalClass.getClassLoader().getResourceAsStream(resourceName)) {
if (is == null) {
throw new IOException("Could not find class file for " + originalClass.getName());
}
ClassReader reader = new ClassReader(is);
InnerClassCollector collector = new InnerClassCollector(originalClass.getName());
reader.accept(collector, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
innerClasses = new HashSet<>(collector.getInnerClasses());
}
try {
for (Class<?> innerClass : originalClass.getDeclaredClasses()) {
innerClasses.add(innerClass.getName());
innerClasses.addAll(findAllInnerClasses(innerClass));
}
} catch (SecurityException ignored) {
}
return innerClasses;
}
private static class InnerClassCollector extends ClassVisitor {
private final String originalClassName;
@Getter
private final Set<String> innerClasses = new HashSet<>();
public InnerClassCollector(String originalClassName) {
super(Opcodes.ASM9);
this.originalClassName = originalClassName.replace('/', '.');
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
String className = name.replace('/', '.');
if (outerName != null) {
String outerClassName = outerName.replace('/', '.');
if (outerClassName.equals(originalClassName)) {
innerClasses.add(className);
}
} else if (className.startsWith(originalClassName + "$")) {
innerClasses.add(className);
}
}
}
}