gpt4 book ai didi

java - 实现选择性类加载器

转载 作者:行者123 更新时间:2023-11-30 05:00:57 24 4
gpt4 key购买 nike

我想在加载时检测类路径上某些类的字节码。由于这些是第三方库,我确切地知道它们何时加载。问题是我需要有选择地进行检测,即仅检测某些类。现在,如果我不使用我的类加载器而是使用其父类来加载类,则该父类将被设置为类类加载器,并且所有简洁的类都由该父类加载,从而有效地使我的类加载器无法使用。所以我需要实现一个父级最后一个类加载器(参见 How to put custom ClassLoader to use? )。

所以我需要自己加载类。如果这些类是系统类(以“java”或“sun”开头),我将委托(delegate)给父类。否则我读取字节码并调用 defineClass(name, byteBuffer, 0, byteBuffer.length); 。但现在java.lang.ClassNotFoundException: java.lang.Object被抛出。

这是代码,任何评论都非常感谢:

public class InstrumentingClassLoader extends ClassLoader {
private final BytecodeInstrumentation instrumentation = new BytecodeInstrumentation();

@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> result = defineClass(name);
if (result != null) {
return result;
}
result = findLoadedClass(name);
if(result != null){
return result;
}
result = super.findClass(name);
return result;
}

private Class<?> defineClass(String name) throws ClassFormatError {
byte[] byteBuffer = null;
if (instrumentation.willInstrument(name)) {
byteBuffer = instrumentByteCode(name);
}
else {
byteBuffer = getRegularByteCode(name);
}
if (byteBuffer == null) {
return null;
}
Class<?> result = defineClass(name, byteBuffer, 0, byteBuffer.length);
return result;
}

private byte[] getRegularByteCode(String name) {
if (name.startsWith("java") || name.startsWith("sun")) {
return null;
}
try {
InputStream is = ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + ".class");
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
} catch (IOException exc) {
return null;
}
}

private byte[] instrumentByteCode(String fullyQualifiedTargetClass) {
try {
String className = fullyQualifiedTargetClass.replace('.', '/');
return instrumentation.transformBytes(className, new ClassReader(fullyQualifiedTargetClass));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

代码可以被执行,例如与:

    InstrumentingClassLoader instrumentingClassLoader = new InstrumentingClassLoader();
Class<?> changedClass = instrumentingClassLoader.loadClass(ClassLoaderTestSubject.class.getName());

ClassLoaderTestSubject应该调用一些其他类,其中被调用的类是检测的目标,但 ClassLoaderTestSubject本身并不...

最佳答案

我建议您使用常规的类加载器策略,即父类加载器优先。但将您想要检测的所有类放入单独的 jar 文件中,并且不要将其添加到应用程序的类路径中。使用扩展 URL 类加载器并知道在其他位置搜索 jar 的类加载器实例化这些类。在这种情况下,所有 JDK 类都会自动识别,并且您的代码会更简单。您不必“思考”是否要检测该类:如果父类加载器未加载该类,则必须检测您的类。

关于java - 实现选择性类加载器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6750392/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com