Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

编译期报错,javassist新增方法报错,javassist.CannotCompileException: [source error] ) is missing #623

Closed
jinglm134 opened this issue Sep 23, 2021 · 5 comments · Fixed by #625

Comments

@jinglm134
Copy link

jinglm134 commented Sep 23, 2021

在source项目下,在simple-app-lib中新增了两个360的jar包,然后编译插件报错:

Execution failed for task ':sample-plugin-app:transformClassesWithShadowTransformForDebug'.

javassist.CannotCompileException: [source error] ) is missing

  • Exception is:
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':sample-plugin-app:transformClassesWithShadowTransformForDebug'
    Caused by: javassist.CannotCompileException: [source error] ) is missing
    at javassist.CtBehavior.setBody(CtBehavior.java:474)
    at javassist.CtBehavior.setBody(CtBehavior.java:440)
    at com.tencent.shadow.core.transform.specific.PackageManagerTransform$setupPackageManagerTransform$$inlined$forEach$lambda$1.transform(PackageManagerTransform.kt:81)
    at com.tencent.shadow.core.transform_kit.AbstractTransformManager.fireAll(AbstractTransformManager.kt:41)
    at com.tencent.shadow.core.transform_kit.AbstractTransform.onTransform(AbstractTransform.kt:61)
    at com.tencent.shadow.core.transform_kit.ClassTransform.transform(ClassTransform.kt:173)
    at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:284)
    at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:247)
    at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:106)
    ... 92 more
    Caused by: compile error: ) is missing
    at javassist.compiler.Parser.parseArgumentList(Parser.java:1352)
    at javassist.compiler.Parser.parseMethodCall(Parser.java:1196)
    at javassist.compiler.Parser.parsePostfix(Parser.java:1054)
    at javassist.compiler.Parser.parseUnaryExpr(Parser.java:904)
    at javassist.compiler.Parser.parseBinaryExpr(Parser.java:794)
    at javassist.compiler.Parser.parseConditionalExpr(Parser.java:739)
    at javassist.compiler.Parser.parseExpression(Parser.java:719)
    at javassist.compiler.Parser.parseReturn(Parser.java:524)
    at javassist.compiler.Parser.parseStatement(Parser.java:287)
    at javassist.compiler.Javac.compileBody(Javac.java:219)
    at javassist.CtBehavior.setBody(CtBehavior.java:466)

对修改字节码不熟,不知道为什么会报这个错误? 猜测1:jar包中代码混淆的原因? 猜测2:jar包中类的包名以数字开头的原因?

@shifujun
Copy link
Collaborator

应该是这段代码出错了:

val newBodyBuilder = StringBuilder()
newBodyBuilder
.append("return ")
.append(ShadowAndroidPackageManagerClassname)
.append(".")
.append(targetMethod.methodInfo.name)
.append("(")
.append(ctClass.name)
.append(".class.getClassLoader(),")
//下面放弃第0个和第1个参数,第0个是this,
//第1个是redirectMethodCallToStaticMethodCall时原本被调用的PackageManager对象。
for (i in 2..newMethod.parameterTypes.size) {
if (i > 2) {
newBodyBuilder.append(',')
}
newBodyBuilder.append("\$${i}")
}
newBodyBuilder.append(");")
newMethod.setBody(newBodyBuilder.toString())

这里报的Caused by: compile error: ) is missing应该是指这段生成的源码在调用方法时缺少最后的大括号,正常来说应该是newBodyBuilder.append(");")添加的。

你要是可以debug的话,可以改一下代码,把newBodyBuilder.toString()打印出来看看。我们也许就知道这里是什么情况造成的错误了。

我估计是这个jar包通过Proguard混淆,把一些变量名改成了Java语言不允许但是JVM允许的字符。

@jinglm134
Copy link
Author

newBodyBuilder没有问题,已经找到问题原因了,原因是jar包混淆指定了混淆后的包名,然后混淆后包名是数字开头,即Java语言不允许但是JVM允许的字符。谢谢了!!

@shifujun
Copy link
Collaborator

我review了一下这个Transform。似乎实现的麻烦了,可能不需要这样重新编译一段代码。我试着重写一下。

@jinglm134
Copy link
Author

newBodyBuilder.append(".class.getClassLoader()") ,for循环里面可以不用判断,直接append(“,$${i}”)

shifujun added a commit to shifujun/Shadow that referenced this issue Sep 24, 2021
修复前对于PackageManagerTransformTest.kt改动的情况无法编译成功。因为setBody时需要编译Java代码片段。存在一些经过Proguard混淆的类使用了非法的字符作为包名,在代码里引用这些类名无法正常编译。

需要引用当前类的class时,先引用这个Placeholder,编译后再直接通过字节码修改替换回原来的名字。

fix Tencent#623
@shifujun
Copy link
Collaborator

这个实现中关键的操作:在调用类中新增静态方法,主要目的是首先要避免直接调用到原先的PackageManager对象上。所以要先变成一个静态方法调用。然后又想获得当前调用类所在的ClassLoader,从而在多插件场景下确定需要哪个插件的PackageManager对象。

这样的话,如果不直接引用当前类的class引用,就只能运行时反射调用栈了。因此能优化的空间也不大。

所以我最后还是选择用一个Placeholder规避这种非法的类名无法编译的问题。

shifujun added a commit that referenced this issue Sep 26, 2021
修复前对于PackageManagerTransformTest.kt改动的情况无法编译成功。因为setBody时需要编译Java代码片段。存在一些经过Proguard混淆的类使用了非法的字符作为包名,在代码里引用这些类名无法正常编译。

需要引用当前类的class时,先引用这个Placeholder,编译后再直接通过字节码修改替换回原来的名字。

fix #623
shifujun added a commit to shifujun/Shadow that referenced this issue May 6, 2022
修复前对于PackageManagerTransformTest.kt改动的情况无法编译成功。因为setBody时需要编译Java代码片段。存在一些经过Proguard混淆的类使用了非法的字符作为包名,在代码里引用这些类名无法正常编译。

需要引用当前类的class时,先引用这个Placeholder,编译后再直接通过字节码修改替换回原来的名字。

fix Tencent#623

(cherry picked from commit d4b6e9e)
shifujun added a commit to shifujun/Shadow that referenced this issue May 6, 2022
修复前对于PackageManagerTransformTest.kt改动的情况无法编译成功。因为setBody时需要编译Java代码片段。存在一些经过Proguard混淆的类使用了非法的字符作为包名,在代码里引用这些类名无法正常编译。

需要引用当前类的class时,先引用这个Placeholder,编译后再直接通过字节码修改替换回原来的名字。

fix Tencent#623

(cherry picked from commit d4b6e9e)
shifujun added a commit that referenced this issue May 7, 2022
修复前对于PackageManagerTransformTest.kt改动的情况无法编译成功。因为setBody时需要编译Java代码片段。存在一些经过Proguard混淆的类使用了非法的字符作为包名,在代码里引用这些类名无法正常编译。

需要引用当前类的class时,先引用这个Placeholder,编译后再直接通过字节码修改替换回原来的名字。

fix #623

(cherry picked from commit d4b6e9e)
shifujun added a commit to shifujun/Shadow that referenced this issue May 7, 2022
修复前对于PackageManagerTransformTest.kt改动的情况无法编译成功。因为setBody时需要编译Java代码片段。存在一些经过Proguard混淆的类使用了非法的字符作为包名,在代码里引用这些类名无法正常编译。

需要引用当前类的class时,先引用这个Placeholder,编译后再直接通过字节码修改替换回原来的名字。

fix Tencent#623

(cherry picked from commit d4b6e9e)
shifujun added a commit to shifujun/Shadow that referenced this issue May 7, 2022
修复前对于PackageManagerTransformTest.kt改动的情况无法编译成功。因为setBody时需要编译Java代码片段。存在一些经过Proguard混淆的类使用了非法的字符作为包名,在代码里引用这些类名无法正常编译。

需要引用当前类的class时,先引用这个Placeholder,编译后再直接通过字节码修改替换回原来的名字。

fix Tencent#623

(cherry picked from commit d4b6e9e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants