我试图将jar文件直接加载到内存中而不将其丢弃到HDD中。我尝试过使用ClassLoader,但是我收到了错误。
这是我的代码:
自定义类加载器
public class CLS_ClassLoader extends ClassLoader {
private byte[] bArrData;
public CLS_ClassLoader(ClassLoader parent, byte[] bArrData) {
super(parent);
this.bArrData = bArrData;
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
return defineClass(name, bArrData, 0,
bArrData.length);
}
}
主要
ClassLoader tParentClsLoader = CLS_ClassLoader.class.getClassLoader();
CLS_ClassLoader tClsLoader = new CLS_ClassLoader(tParentClsLoader, fileToByteArray("D:/App.jar"));
Class<?> tClass = null;
try {
tClass = tClsLoader.loadClass("pkg_main.CLS_Main");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
输出
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1347093252 in class file pkg_main/CLS_Main
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at pkg_main.CLS_ClassLoader.loadClass(CLS_ClassLoader.java:20)
at pkg_main.CSL_Main.main(CSL_Main.java:27)
我的想法是获取一个加密的jar文件,在运行时解密并直接加载到内存中。
抱歉打字错误,我说英语不好。提前谢谢!
答案 0 :(得分:3)
你的主要错误是defineClass(...)期望类字节而你正在用整个jar文件提供它。如果类字节不以0xCAFEBABE(典型的Java类文件头)开头,则抛出实际异常。因此,您需要一个额外的步骤来对jar文件中的类进行排序。以下实现演示了这个想法:
class CCLoader extends ClassLoader {
private Map<String, byte[]> classes = new HashMap<String, byte[]>();
public CCLoader(InputStream in) {
super(CCLoader.class.getClassLoader());
try {
JarInputStream jis = new JarInputStream(in);
JarEntry je = null;
String entryName = null;
while ((je = jis.getNextJarEntry()) != null) {
entryName = je.getName();
if (je.getName().endsWith(".class")) {
byte[] classBytes = readClass(jis);
String canonicalName = entryName.replaceAll("/", ".").replaceAll(".class", "");
classes.put(canonicalName, classBytes);
}
}
jis.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] readClass(InputStream stream) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while(true){
int qwe = stream.read();
if(qwe == -1) break;
baos.write(qwe);
}
return baos.toByteArray();
}
public Class loadClass(String name) throws ClassNotFoundException {
try {
return this.getParent().loadClass(name);
} catch (ClassNotFoundException e) {
return findClass(name);
}
}
public Class findClass(String name) throws ClassNotFoundException {
byte[] classBytes = classes.get(name);
return defineClass(name, classBytes, 0, classBytes.length);
}
}
按照你的例子你可以这样尝试:
ClassLoader tClsLoader = new CCLoader(new FileInputStream("C:/commons-io-2.0.1.jar"));
Class<?> tClass = tClsLoader.loadClass("org.apache.commons.io.FileExistsException");