简体   繁体   中英

javassist ; is missing

Could anyone tell what is wrong with my code ? when using javassist to insert code , it show error "Caused by: compile error: ; is missing"; But I double check , there no ; missing at all. Is there some limitation of javassist here?

        ClassPool cp = ClassPool.getDefault();
        cp.importPackage("com.mysql.cj");

        CtClass cc = cp.get(clzname);
        CtMethod ms = cc.getDeclaredMethod(
                "execute");
        StringBuilder sb = new StringBuilder();
        sb.append("String sql = ((PreparedQuery) this.query).getOriginalSql();");
        sb.append("QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();\n" +
                "        for (BindValue o : bindings.getBindValues()) {\n" +
                "            sql = sql.replaceFirst(\"\\\\?\", new String(o.getByteValue()));\n" +
                "        }");

        sb.append(
                "System.out.println( sql);");

        ms.insertBefore(sb.toString());
        byteCode = cc.toBytecode();

The javadoc for insertBefore says:

https://www.javassist.org/html/javassist/CtBehavior.html#insertBefore(java.lang.String)

Parameters: src - the source code representing the inserted bytecode. It must be a single statement or block.

So, wrap the code in curly braces so it is a single block.

I solved my bug by replacing the for loop.

It seems javaassit not support convient for loop, it has to be change it into for(int i= 0; i< lenth; i++) format;

And thanks to @kutschem , the code also need to be wrapped by curly braces.

ClassPool cp = ClassPool.getDefault();
        cp.importPackage("com.mysql.cj");

        CtClass cc = cp.get(clzname);
        CtMethod ms = cc.getDeclaredMethod(
                "execute");

        ms.insertBefore("{\n" +
                "            String sql = ((PreparedQuery) this.query).getOriginalSql();\n" +
                "            QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();\n" +
                "            for (int i =0; i < bindings.getBindValues().length; i++ ) sql = sql.replaceFirst(\"\\\\?\", new String(bindings.getBindValues()[i].getByteValue()));\n" +
                "            System.out.println(sql);\n" +
                "        }");

        byteCode = cc.toBytecode();

In addition to wrapping your code into curly braces like @kutschem said, I also have an idea for you how to concatenate your string more easily, without using a StringBuilder . As a positive side effect, you also get line breaks:

String codeToBeInserted = String.join("\n",
  "{",
  "  String sql = ((PreparedQuery) this.query).getOriginalSql();",
  "  QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();",
  "  for (BindValue o : bindings.getBindValues()) {",
  "    sql = sql.replaceFirst(\"\\\\?\", new String(o.getByteValue()));",
  "  }",
  "  System.out.println(sql);",
  "}"
);
System.out.println(codeToBeInserted);

String.join is available since Java 8. The console output would be:

{
  String sql = ((PreparedQuery) this.query).getOriginalSql();
  QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();
  for (BindValue o : bindings.getBindValues()) {
    sql = sql.replaceFirst("\\?", new String(o.getByteValue()));
  }
  System.out.println(sql);
}

To me, your code looks okay syntactically, especially the replaceFirst meant to replace ? by a fixed value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM