如Pete所述,可以使用ASM字节码库来完成此操作。实际上,该库实际上带有一个专门用于处理这些类名重新映射(
RemappingClassAdapter)的类。这是使用此类的类加载器的示例:
public class MagicClassLoader extends ClassLoader { private final String defaultPackageName; public MagicClassLoader(String defaultPackageName) { super(); this.defaultPackageName = defaultPackageName; } public MagicClassLoader(String defaultPackageName, ClassLoader parent) { super(parent); this.defaultPackageName = defaultPackageName; } @Override public Class<?> loadClass(String name) throws ClassNotFoundException { byte[] bytepre = ...; // I will leave this part up to you byte[] remappedBytepre; try { remappedBytepre = rewriteDefaultPackageClassNames(bytepre); } catch (IOException e) { throw new RuntimeException("Could not rewrite class " + name); } return defineClass(name, remappedBytepre, 0, remappedBytepre.length); } public byte[] rewriteDefaultPackageClassNames(byte[] bytepre) throws IOException { ClassReader classReader = new ClassReader(bytepre); ClassWriter classWriter = new ClassWriter(classReader, 0); Remapper remapper = new DefaultPackageClassNameRemapper(); classReader.accept( new RemappingClassAdapter(classWriter, remapper), 0 ); return classWriter.toByteArray(); } class DefaultPackageClassNameRemapper extends Remapper { @Override public String map(String typeName) { boolean hasPackageName = typeName.indexOf('.') != -1; if (hasPackageName) { return typeName; } else { return defaultPackageName + "." + typeName; } } }}为了说明这一点,我创建了两个类,它们都属于默认包:
public class Customer {}和
public class Order { private Customer customer; public Order(Customer customer) { this.customer = customer; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; }}这是任何重新映射
Order之前 的清单:
> javap -private -c命令从“ Order.java”编译公共类Order扩展java.lang.Object {私人客户客户;公共秩序(客户); 码: 0:加载_0 1:调用特殊#10; //方法java / lang / Object。“” :()V 4:aload_0 5:aload_1 6:普特菲尔德#13;//字段客户:LCustomer; 9:返回公共客户getCustomer(); 码: 0:加载_0 1:getfield#13;//字段客户:LCustomer; 4:阿伦public void setCustomer(Customer); 码: 0:加载_0 1:aload_1 2:putfield#13;//字段客户:LCustomer; 5:返回}这是重新映射
Order后 的列表(
com.mycompany用作默认软件包):
> javap -private -c命令从“ Order.java”编译公共类com.mycompany.Order扩展了com.mycompany.java.lang.Object {私人com.mycompany.Customer客户;公共com.mycompany.Order(com.mycompany.Customer); 码: 0:加载_0 1:调用特殊#30; //方法“ com.mycompany.java/lang/Object"."":()V 4:aload_0 5:aload_1 6:普特菲尔德#32;//字段客户:Lcom.mycompany.Customer; 9:返回公共com.mycompany.Customer getCustomer(); 码: 0:加载_0 1:getfield#32;//字段客户:Lcom.mycompany.Customer; 4:阿伦公共无效setCustomer(com.mycompany.Customer); 码: 0:加载_0 1:aload_1 2:putfield#32;//字段客户:Lcom.mycompany.Customer; 5:返回}如您所见,重新映射更改了
Order对的所有引用
com.mycompany.Order和对的所有
Customer引用
com.mycompany.Customer。
该类加载器将必须加载以下任一类的所有类:
- 属于默认软件包,或
- 使用属于默认软件包的其他类。



