gpt4 book ai didi

Javassist - 如何将方法注入(inject) JAR 中的类

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:17:54 24 4
gpt4 key购买 nike

我正在从 JAR 文件中读取一个类并注入(inject)一个函数。我如何将其写回 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(系统找不到指定的路径)

最佳答案

我想 Javassist 中没有简单的方法可以更新 JAR 并将更新的类替换为新类。所以我创建了一个 JarHandler 类,它只接收参数。

这是执行注入(inject)的主类

  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。

关于Javassist - 如何将方法注入(inject) JAR 中的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22591903/

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