我正在从JAR
文件中读取一个类并注入一个函数。如何将其写回JAR文件?
// Load the class representation
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath( "c:/Test.jar" );
CtClass cc = pool.get("com.test.TestFunction");
CtMethod m = CtNewMethod.make("public void test2() { System.out.println(\"test2\"); }", cc);
cc.addMethod(m);
CtMethod cm = cc.getDeclaredMethod("test1", new CtClass[0]);
cm.insertBefore("{ test2();}");
cc.writeFile("c:/Test.jar"); // Fails here
线程中的异常" main" java.io.FileNotFoundException
:c:\ Test.jar \ com \ test \ TestFunction.class(系统找不到指定的路径)
答案 0 :(得分:8)
我想Javassist中没有简单的方法可以更新JAR并用新类替换更新的类。所以我创建了一个简单接收参数的JarHandler类。
这是进行注射的主要类
public static void main(String args[]){
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath( "c:/Test.jar" );
CtClass cc = pool.get("com.test.TestFunction");
CtMethod m = CtNewMethod.make("public void test2() { System.out.println(\"test2\"); }", cc);
cc.addMethod(m);
CtMethod cm = cc.getDeclaredMethod("test1", new CtClass[0]);
cm.insertBefore("{ test2();}");
byte[] b = cc.toBytecode(); // convert the new class to bytecode.
pool.removeClassPath(cp); // need to remove the classpath to release connection to JAR file so we can update it.
JarHandler jarHandler = new JarHandler();
jarHandler.replaceJarFile("C:/Test.jar", b, "com/test/TestFunction.class");
}
这是JarHandler类
public class JarHandler{
public void replaceJarFile(String jarPathAndName,byte[] fileByteCode,String fileName) throws IOException {
File jarFile = new File(jarPathAndName);
File tempJarFile = new File(jarPathAndName + ".tmp");
JarFile jar = new JarFile(jarFile);
boolean jarWasUpdated = false;
try {
=
JarOutputStream tempJar =
new JarOutputStream(new FileOutputStream(tempJarFile));
// Allocate a buffer for reading entry data.
byte[] buffer = new byte[1024];
int bytesRead;
try {
// Open the given file.
try {
// Create a jar entry and add it to the temp jar.
JarEntry entry = new JarEntry(fileName);
tempJar.putNextEntry(entry);
tempJar.write(fileByteCode);
} catch (Exception ex) {
System.out.println(ex);
// Add a stub entry here, so that the jar will close without an
// exception.
tempJar.putNextEntry(new JarEntry("stub"));
}
// Loop through the jar entries and add them to the temp jar,
// skipping the entry that was added to the temp jar already.
InputStream entryStream = null;
for (Enumeration entries = jar.entries(); entries.hasMoreElements(); ) {
// Get the next entry.
JarEntry entry = (JarEntry) entries.nextElement();
// If the entry has not been added already, so add it.
if (! entry.getName().equals(fileName)) {
// Get an input stream for the entry.
entryStream = jar.getInputStream(entry);
tempJar.putNextEntry(entry);
while ((bytesRead = entryStream.read(buffer)) != -1) {
tempJar.write(buffer, 0, bytesRead);
}
}else
System.out.println("Does Equal");
}
if(entryStream!=null)
entryStream.close();
jarWasUpdated = true;
}
catch (Exception ex) {
System.out.println(ex);
// IMportant so the jar will close without an
// exception.
tempJar.putNextEntry(new JarEntry("stub"));
}
finally {
tempJar.close();
}
}
finally {
jar.close();
if (! jarWasUpdated) {
tempJarFile.delete();
}
}
if (jarWasUpdated) {
if(jarFile.delete()){
tempJarFile.renameTo(jarFile);
System.out.println(jarPathAndName + " updated.");
}else
System.out.println("Could Not Delete JAR File");
}
}
此函数只是通过向其写入新的类字节码来创建临时JAR。 然后通过当前JAR的所有条目并将其所有条目写入临时 JAR文件除了正在更新的条目(字节码已经写入上面)。然后它删除当前的JAR并使用相同的JAR名称将其替换为临时JAR。
答案 1 :(得分:1)