对于我正在做的项目,我需要使用javassist对外部jar文件中的方法进行字节码操作。这工作正常,除了我有一个源代码错误,我无法看出问题是什么。所以我创建了一个Exception变量,捕获了异常,并打印了消息和堆栈跟踪元素,如下所示:
StackTraceElement[] e = randomexception.getStackTrace();
System.out.println(randomexception.getMessage());
for(int i = 0; i < e.length; i++){
StackTraceElement ste = e[i];
String s = ste.toString();
System.out.println(s);
}
我收到了这个错误:
cannot find java.net.SocketAddress
javassist.CtBehavior.insertAt(CtBehavior.java:1210)
RainbowBansTransAgent.Transformationer.transform(Transformationer.java:26)
RainbowBansTransAgent.Transformationer.transform(Transformationer.java:68)
sun.instrument.TransformerManager.transform(Unknown Source)
sun.instrument.InstrumentationImpl.transform(Unknown Source)
sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
sun.instrument.InstrumentationImpl.retransformClasses(Unknown Source)
RainbowBansTransAgent.TransAgent.premain(TransAgent.java:106)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
sun.instrument.InstrumentationImpl.loadClassAndStartAgent(Unknown Source)
sun.instrument.InstrumentationImpl.loadClassAndCallPremain(Unknown Source)
但是我的源代码根本没有调用SocketAddress类。我在内部编辑代码的方法确实如此,但我没有编辑该方法,所以我认为没有理由不这样做。
方法是:
checkIfShouldDisconnect(SocketAddress address)
我尝试使用ClassLoader.loadClass方法加载java.net.SocketAddress类。我也尝试将源代码放在括号中。我看了一下javassist的限制,但我的代码看起来很好。我将堆栈跟踪追溯到用于构造CannotCompileEception的NotFoundException。
我将在下面附上我的代码:
TransAgent.java
package RainbowBansTransAgent;
import java.io.File;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.util.ArrayList;
import java.util.jar.JarFile;
import javassist.ClassPool;
import javassist.NotFoundException;
public class TransAgent{
public static TransAgent ta;
public static ClassPool coldwater = new ClassPool();
public static File dir = new File("RainbowBans");
public static ArrayList<Long> ln = new ArrayList<Long>();
public static Exception randomexception;
public static void main(String[] args){
System.out.println("JarFile looking at: " + getRainbowPath() + "Rainbow.jar");
if(BooleanKeys.premain) System.out.println("Premain agent loaded");
else{
System.out.println("Premain agent not loaded!");
ln.add(16185131914L);
BooleanKeys.error = true;
}
if(BooleanKeys.transformer_loaded) System.out.println("Transformation agent loaded!");
else{
System.out.println("Transformation agent not loaded!");
ln.add(16185131914L);
BooleanKeys.error = true;
}
if(BooleanKeys.returns_line && BooleanKeys.returned_bytes) System.out.println("Transformation worked successfully");
else if (BooleanKeys.returned_bytes && (NumberKeys.line_Inserted_At != 409)) System.out.println("Transformation worked successfully, but code inserted at the wrong line");
else if (BooleanKeys.error){
System.out.println("There was an error in the transformation! Please report the following:");
System.out.println("Error codes: ");
for (int i = 0; i < ln.size(); i++){
System.out.println(ln.get(i));
}
if(ln.contains(14152061521144L)){
System.out.println("This indicates that the joebkt.PlayerList class could not be located!");
}else if (ln.contains(69125L)){
if(BooleanKeys.IOFromEntry){
System.out.println("This indicates the Rainbow.jar could not be found! Stack trace:");
StackTraceElement[] e = randomexception.getStackTrace();
for(int i = 0; i < e.length; i++){
StackTraceElement ste = e[i];
String s = ste.toString();
System.out.println(s);
}
}else{
System.out.println("This indicates that there was an error returning the inserted bytecode to the joebkt.PlayerList class!");
}
}else if (ln.contains(16185131914L)){
System.out.println("This indicates that the transformation stopped either at the premain or the transformation agent!");
}else if (ln.contains(31513169125L)){
System.out.println("This indicates an error in adding the code into the joebkt.PLayerList class! Stack trace:");
StackTraceElement[] e = randomexception.getStackTrace();
System.out.println(randomexception.getMessage());
for(int i = 0; i < e.length; i++){
StackTraceElement ste = e[i];
String s = ste.toString();
System.out.println(s);
}
}else if (ln.contains(31211919161208L)){
System.out.println("This indicates an error with javassist getting to Rainbow.jar!");
}else if (ln.contains(131549625L)){
System.out.println("This indicates the joebkt.PlayerList class could not be retransformed!");
}else if(ln.contains(514201825L)){
System.out.println("This indicates that the JarEntry for the joebkt.PlayerList class could not be made!");
}
else{
System.out.println("Error code misspelt! Please report");
}
}else if (BooleanKeys.frozen){
System.out.println("The class cannot be edited!");
}else if (BooleanKeys.found_class){
System.out.println("At least the class was found. But there were errors in the process.");
}else{
System.out.println("NO IDEA WHAT HAPPENED!!!");
}
BooleanKeys.premain = false;
}
public TransAgent(){
ta = this;
}
public static void agentmain(String args, Instrumentation inst){
premain(args, inst);
}
public static void premain(String agentArgs, Instrumentation inst) {
try {
inst.appendToSystemClassLoaderSearch(new JarFile(getRainbowPath() + "Rainbow.jar", true));
} catch (IOException e1) {
e1.printStackTrace();
}
BooleanKeys.premain = true;
try {
inst.addTransformer(new Transformationer(), true);
coldwater.insertClassPath(getRainbowPath() + "Rainbow.jar");
Class<?> classs = Class.forName("joebkt.PlayerList", false, joebkt.PlayerList.class.getClassLoader());
Class<?>[] classes = {classs};
inst.retransformClasses(classes);
BooleanKeys.premain_done = true;
} catch (NotFoundException e) {
BooleanKeys.error = true;
ln.add(31211919161208L);
}catch (Exception e){
e.printStackTrace();
}
}
public static String getRainbowPath() {
return new File(".").getAbsoluteFile().getParent() + File.separator;
}
}
class BooleanKeys{
public static boolean premain = false;
public static boolean transformer_loaded = false;
public static boolean entry = false;
public static boolean premain_done = false;
public static boolean returns_line = false;
public static boolean error = false;
public static boolean frozen = false;
public static boolean found_class = false;
public static boolean returned_bytes = false;
public static boolean IOFromEntry = false;
}
class NumberKeys{
public static int line_Inserted_At = 0;
}
Transformationer.java
package RainbowBansTransAgent;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import joebkt.PlayerList;
public class Transformationer implements ClassFileTransformer {
public byte[] transform(String arg1){
try {
ClassLoader.getSystemClassLoader().loadClass("java.net.SocketAddress");
CtClass cc = TransAgent.coldwater.get(arg1);
if(cc.isFrozen()){
BooleanKeys.frozen = true;
return null;
}else{
cc.getClassFile().setMajorVersion(javassist.bytecode.ClassFile.JAVA_4);
CtMethod m = cc.getDeclaredMethod("checkIfShouldDisconnect");
int n = m.insertAt(409, true, "{java.lang.String var4 = var5.d();}");
if(n == 409){
BooleanKeys.returns_line = true;
NumberKeys.line_Inserted_At = 409;
}else{
BooleanKeys.returns_line = false;
NumberKeys.line_Inserted_At = n;
}
System.out.println("Code inserted at line " + n);
Class<PlayerList> cls = joebkt.PlayerList.class;
cls.getClassLoader().loadClass(arg1);
return cc.toBytecode();
}
} catch (IOException e) {
BooleanKeys.error = true;
TransAgent.ln.add(69125L);
} catch (CannotCompileException e) {
BooleanKeys.error = true;
TransAgent.ln.add(31513169125L);
TransAgent.randomexception = e;
} catch (ClassNotFoundException e) {
BooleanKeys.error = true;
TransAgent.ln.add(14152061521144L);
} catch (NotFoundException e) {
BooleanKeys.error = true;
TransAgent.ln.add(14152061521144L);
}
return null;
}
@Override
public byte[] transform(ClassLoader arg0, String className, Class<?> arg2,
ProtectionDomain arg3, byte[] arg4)
throws IllegalClassFormatException {
BooleanKeys.transformer_loaded = true;
byte[] b = null;
String realName = className.replaceAll("/", ".");
if(realName.equals("joebkt.PlayerList")){
if(BooleanKeys.returned_bytes){
return null;
}else{
BooleanKeys.found_class = true;
b = transform(realName);
if(b !=null){
BooleanKeys.returned_bytes = true;
}
}
}
else System.out.println("Class name " + realName + " is not what we're looking for!");
return b;
}
}
TransAgent是从另一个JAR文件的ProcessBuilder加载的。
我的问题是,我的源代码有什么错误,我该如何解决?