正如 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[] bytecode = ...; // I will leave this part up to you
byte[] remappedBytecode;
try {
remappedBytecode = rewriteDefaultPackageClassNames(bytecode);
} catch (IOException e) {
throw new RuntimeException("Could not rewrite class " + name);
}
return defineClass(name, remappedBytecode, 0, remappedBytecode.length);
}
public byte[] rewriteDefaultPackageClassNames(byte[] bytecode) throws IOException {
ClassReader classReader = new ClassReader(bytecode);
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”
公共类订单扩展 java.lang.Object{
私人客户客户;
公共秩序(客户);
代码:
0:aload_0
1:调用特殊#10;//方法 java/lang/Object."":()V
4:aload_0
5:aload_1
6:放置场#13;//字段客户:LCustomer;
9:返回
公共客户 getCustomer();
代码:
0:aload_0
1:获取字段#13;//字段客户:LCustomer;
4:返回
公共无效 setCustomer(客户);
代码:
0:aload_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:aload_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:aload_0
1:获取字段#32;//字段客户:Lcom.mycompany.Customer;
4:返回
公共无效 setCustomer(com.mycompany.Customer);
代码:
0:aload_0
1:aload_1
2:putfield #32;//字段客户:Lcom.mycompany.Customer;
5:返回
}
如您所见,重新映射已更改对 的所有Order
引用com.mycompany.Order
和对 的所有Customer
引用com.mycompany.Customer
。
这个类加载器必须加载所有类: