Skip to content

Commit 66a86fb

Browse files
committed
1、修复收集切面类编译的bug
1 parent 74c8372 commit 66a86fb

6 files changed

Lines changed: 150 additions & 121 deletions

File tree

android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/Conversions.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,4 +235,12 @@ static Class<?> getReturnClass(String className){
235235
}
236236
return null;
237237
}
238+
239+
public static void collectObject(Object o){
240+
241+
}
242+
243+
public static void collectThrowable(Throwable e){
244+
e.printStackTrace();
245+
}
238246
}

android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/ReplaceBaseClassVisitor.kt

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.flyjingfish.android_aop_plugin.scanner_visitor
33
import com.flyjingfish.android_aop_plugin.utils.AppClasses
44
import com.flyjingfish.android_aop_plugin.utils.ClassPoolUtils
55
import com.flyjingfish.android_aop_plugin.utils.InitConfig
6-
import com.flyjingfish.android_aop_plugin.utils.Utils
6+
import com.flyjingfish.android_aop_plugin.utils.Utils.CONVERSIONS_CLASS
77
import com.flyjingfish.android_aop_plugin.utils.Utils.dotToSlash
88
import com.flyjingfish.android_aop_plugin.utils.Utils.slashToDot
99
import com.flyjingfish.android_aop_plugin.utils.Utils.slashToDotClassName
@@ -15,11 +15,11 @@ import org.objectweb.asm.ClassVisitor
1515
import org.objectweb.asm.Label
1616
import org.objectweb.asm.MethodVisitor
1717
import org.objectweb.asm.Opcodes
18-
import org.objectweb.asm.Type
1918
import org.objectweb.asm.commons.AdviceAdapter
2019
import org.objectweb.asm.signature.SignatureReader
2120
import org.objectweb.asm.signature.SignatureVisitor
2221
import org.objectweb.asm.signature.SignatureWriter
22+
import kotlin.math.max
2323

2424
open class ReplaceBaseClassVisitor(
2525
classVisitor: ClassVisitor
@@ -210,20 +210,30 @@ open class ReplaceBaseClassVisitor(
210210
mv.visitInsn(DUP);//压入栈
211211
//弹出一个对象所在的地址,进行初始化操作,构造函数默认为空,此时栈大小为1(到目前只有一个局部变量)
212212
mv.visitMethodInsn(INVOKESPECIAL, dotToSlash(className),"<init>","()V",false)
213-
mv.visitInsn(POP) // 保证 try 分支栈深为 0
213+
mv.visitMethodInsn(
214+
INVOKESTATIC,
215+
dotToSlash(CONVERSIONS_CLASS),
216+
"collectObject",
217+
"(Ljava/lang/Object;)V",
218+
false
219+
)
214220

215221
mv.visitLabel(tryEnd)
216-
mv.visitJumpInsn(Opcodes.GOTO, tryCatchBlockEnd)
222+
mv.visitJumpInsn(GOTO, tryCatchBlockEnd)
217223

218224
mv.visitLabel(labelCatch)
219-
mv.visitVarInsn(Opcodes.ASTORE, 0)
220-
221-
mv.visitVarInsn(Opcodes.ALOAD, 0)
225+
mv.visitFrame(
226+
Opcodes.F_SAME1, // 局部变量和上一个 frame 相同,但栈上多 1 个
227+
0, // nLocal = 0 (static 方法没有局部变量)
228+
null, // locals
229+
1, // nStack = 1
230+
arrayOf("java/lang/NoClassDefFoundError") // catch 捕获的异常对象在栈顶
231+
)
222232
mv.visitMethodInsn(
223-
Opcodes.INVOKEVIRTUAL,
224-
"java/lang/NoClassDefFoundError",
225-
"printStackTrace",
226-
"()V",
233+
INVOKESTATIC,
234+
dotToSlash(CONVERSIONS_CLASS),
235+
"collectThrowable",
236+
"(Ljava/lang/Throwable;)V",
227237
false
228238
)
229239

@@ -236,7 +246,11 @@ open class ReplaceBaseClassVisitor(
236246
}
237247

238248
override fun visitMaxs(maxStack: Int, maxLocals: Int) {
239-
super.visitMaxs(maxStack + 4, maxLocals)
249+
val tryCatchMaxStack = 2
250+
251+
val finalMaxStack = max(maxStack, tryCatchMaxStack)
252+
253+
super.visitMaxs(finalMaxStack, maxLocals)
240254
}
241255

242256
override fun onMethodExit(opcode: Int) {

android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/WovenIntoCode.kt

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,38 @@ import kotlinx.metadata.isSuspend
5454
import kotlinx.metadata.jvm.KotlinClassMetadata
5555
import kotlinx.metadata.jvm.Metadata
5656
import kotlinx.metadata.jvm.signature
57-
import org.gradle.api.Project
58-
import org.objectweb.asm.*
57+
import org.objectweb.asm.AnnotationVisitor
58+
import org.objectweb.asm.ClassReader
59+
import org.objectweb.asm.ClassVisitor
60+
import org.objectweb.asm.ClassWriter
5961
import org.objectweb.asm.ClassWriter.COMPUTE_FRAMES
6062
import org.objectweb.asm.ClassWriter.COMPUTE_MAXS
61-
import org.objectweb.asm.Opcodes.*
63+
import org.objectweb.asm.FieldVisitor
64+
import org.objectweb.asm.Label
65+
import org.objectweb.asm.MethodVisitor
66+
import org.objectweb.asm.ModuleVisitor
67+
import org.objectweb.asm.Opcodes
68+
import org.objectweb.asm.Opcodes.ACC_ABSTRACT
69+
import org.objectweb.asm.Opcodes.ACC_FINAL
70+
import org.objectweb.asm.Opcodes.ACC_PUBLIC
71+
import org.objectweb.asm.Opcodes.ACC_STATIC
72+
import org.objectweb.asm.Opcodes.ALOAD
73+
import org.objectweb.asm.Opcodes.ASM9
74+
import org.objectweb.asm.Opcodes.DLOAD
75+
import org.objectweb.asm.Opcodes.DUP
76+
import org.objectweb.asm.Opcodes.FLOAD
77+
import org.objectweb.asm.Opcodes.GOTO
78+
import org.objectweb.asm.Opcodes.ILOAD
79+
import org.objectweb.asm.Opcodes.INVOKESPECIAL
80+
import org.objectweb.asm.Opcodes.INVOKESTATIC
81+
import org.objectweb.asm.Opcodes.IRETURN
82+
import org.objectweb.asm.Opcodes.LLOAD
83+
import org.objectweb.asm.Opcodes.NEW
84+
import org.objectweb.asm.Opcodes.RETURN
85+
import org.objectweb.asm.Opcodes.V1_8
86+
import org.objectweb.asm.RecordComponentVisitor
87+
import org.objectweb.asm.Type
88+
import org.objectweb.asm.TypePath
6289
import org.objectweb.asm.commons.AdviceAdapter
6390
import org.objectweb.asm.tree.LocalVariableNode
6491
import org.objectweb.asm.tree.MethodNode
@@ -977,7 +1004,7 @@ object WovenIntoCode {
9771004
}
9781005

9791006
fun wovenStaticCode(cw:ClassWriter,thisClassName:String){
980-
val mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "<clinit>", "()V", null, null)
1007+
val mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null)
9811008
for (moduleName in AppClasses.getAllModuleNames()) {
9821009
val tryStart = Label()
9831010
val tryEnd = Label()
@@ -990,36 +1017,51 @@ object WovenIntoCode {
9901017
labelCatch,
9911018
"java/lang/NoClassDefFoundError"
9921019
)
1020+
9931021
mv.visitLabel(tryStart)
9941022

9951023
val className1 = "$thisClassName\$Inner${thisClassName.computeMD5()}_${moduleName.computeMD5()}"
996-
mv.visitTypeInsn(AdviceAdapter.NEW,Utils.dotToSlash(className1))
997-
mv.visitInsn(AdviceAdapter.DUP)
998-
mv.visitMethodInsn(AdviceAdapter.INVOKESPECIAL,Utils.dotToSlash(className1),"<init>","()V",false)
999-
mv.visitInsn(POP) // 保证 try 分支栈深为 0
1024+
mv.visitTypeInsn(NEW, Utils.dotToSlash(className1))
1025+
mv.visitInsn(DUP)
1026+
mv.visitMethodInsn(
1027+
INVOKESPECIAL,
1028+
Utils.dotToSlash(className1),
1029+
"<init>",
1030+
"()V",
1031+
false
1032+
)
1033+
mv.visitMethodInsn(
1034+
INVOKESTATIC,
1035+
dotToSlash(CONVERSIONS_CLASS),
1036+
"collectObject",
1037+
"(Ljava/lang/Object;)V",
1038+
false
1039+
)
10001040

10011041
mv.visitLabel(tryEnd)
1002-
mv.visitJumpInsn(Opcodes.GOTO, tryCatchBlockEnd)
1042+
mv.visitJumpInsn(GOTO, tryCatchBlockEnd)
10031043

10041044
mv.visitLabel(labelCatch)
1005-
mv.visitVarInsn(Opcodes.ASTORE, 0)
1006-
1007-
mv.visitVarInsn(Opcodes.ALOAD, 0)
1045+
mv.visitFrame(
1046+
Opcodes.F_SAME1, // 局部变量和上一个 frame 相同,但栈上多 1 个
1047+
0, // nLocal = 0 (static 方法没有局部变量)
1048+
null, // locals
1049+
1, // nStack = 1
1050+
arrayOf("java/lang/NoClassDefFoundError") // catch 捕获的异常对象在栈顶
1051+
)
10081052
mv.visitMethodInsn(
1009-
Opcodes.INVOKEVIRTUAL,
1010-
"java/lang/NoClassDefFoundError",
1011-
"printStackTrace",
1012-
"()V",
1053+
INVOKESTATIC,
1054+
dotToSlash(CONVERSIONS_CLASS),
1055+
"collectThrowable",
1056+
"(Ljava/lang/Throwable;)V",
10131057
false
10141058
)
10151059

10161060
mv.visitLabel(tryCatchBlockEnd)
1017-
1018-
10191061
}
10201062

10211063
mv.visitInsn(RETURN)
1022-
mv.visitMaxs(0, 0)
1064+
mv.visitMaxs(2, 0)
10231065
mv.visitEnd()
10241066
}
10251067
private fun wovenMethodCode(cw:ClassWriter, superClassName:String, superMethodName:String, methodName:String, methodDescriptor:String, methodAccess:Int,methodNode:MethodNode? ,argInfos:List<LocalVariableNode>){
@@ -1122,7 +1164,7 @@ object WovenIntoCode {
11221164
mv.visitEnd()
11231165

11241166

1125-
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "<clinit>", "()V", null, null)
1167+
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null)
11261168
val map = WovenInfoUtils.getAopInstances()
11271169
if (map.isNotEmpty()) {
11281170
map.forEach { (key, value) ->
@@ -1163,7 +1205,7 @@ object WovenIntoCode {
11631205
mv.visitEnd()
11641206

11651207

1166-
mv = cw.visitMethod(ACC_PUBLIC+ACC_STATIC, "<clinit>", "()V", null, null);
1208+
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
11671209
val map: MutableMap<String,AopCollectClass> = value
11681210
if (map.isNotEmpty()) {
11691211
val iterator = map.iterator();

android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -503,35 +503,12 @@ abstract class AssembleAndroidAopTask : DefaultTransformTask() {
503503
val byteArray = inputs.readAllBytes()
504504
if (byteArray.isNotEmpty()){
505505
try {
506-
val cr = ClassReader(byteArray)
507-
val cw = ClassWriter(cr,0)
508-
var thisHasStaticClock = false
509-
val cv = object : ReplaceBaseClassVisitor(cw) {
510-
override fun visitMethod(
511-
access: Int,
512-
name: String,
513-
descriptor: String,
514-
signature: String?,
515-
exceptions: Array<String?>?
516-
): MethodVisitor? {
517-
val mv = super.visitMethod(
518-
access,
519-
name,
520-
descriptor,
521-
signature,
522-
exceptions
523-
)
524-
thisHasStaticClock = isHasStaticClock
525-
return ReplaceInvokeMethodVisitor(mv,clazzName,oldSuperName)
526-
}
527-
}
528-
cr.accept(cv, 0)
529-
530-
if (!thisHasStaticClock){
531-
WovenIntoCode.wovenStaticCode(cw, thisClassName)
532-
}
533-
534-
val newByteArray = cw.toByteArray()
506+
// val newByteArray = try {
507+
// aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,WovenInfoUtils.getWovenClassWriterFlags(),WovenInfoUtils.getWovenParsingOptions())
508+
// } catch (e: Exception) {
509+
// aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,WovenInfoUtils.getWovenClassWriterFlags2(),WovenInfoUtils.getWovenParsingOptions2())
510+
// }
511+
val newByteArray = aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,0,0)
535512
newByteArray.inputStream().use {
536513
saveEntryCache(directory,jarEntryName,it)
537514
}
@@ -768,35 +745,12 @@ abstract class AssembleAndroidAopTask : DefaultTransformTask() {
768745
val byteArray = inputs.readAllBytes()
769746
if (byteArray.isNotEmpty()){
770747
try {
771-
val cr = ClassReader(byteArray)
772-
val cw = ClassWriter(cr,0)
773-
var thisHasStaticClock = false
774-
val cv = object : ReplaceBaseClassVisitor(cw) {
775-
override fun visitMethod(
776-
access: Int,
777-
name: String,
778-
descriptor: String,
779-
signature: String?,
780-
exceptions: Array<String?>?
781-
): MethodVisitor? {
782-
val mv = super.visitMethod(
783-
access,
784-
name,
785-
descriptor,
786-
signature,
787-
exceptions
788-
)
789-
thisHasStaticClock = isHasStaticClock
790-
return ReplaceInvokeMethodVisitor(mv,clazzName,oldSuperName)
791-
}
792-
}
793-
cr.accept(cv, 0)
794-
795-
if (!thisHasStaticClock){
796-
WovenIntoCode.wovenStaticCode(cw, thisClassName)
797-
}
798-
799-
val newByteArray = cw.toByteArray()
748+
// val newByteArray = try {
749+
// aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,WovenInfoUtils.getWovenClassWriterFlags(),WovenInfoUtils.getWovenParsingOptions())
750+
// } catch (e: Exception) {
751+
// aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,WovenInfoUtils.getWovenClassWriterFlags2(),WovenInfoUtils.getWovenParsingOptions2())
752+
// }
753+
val newByteArray = aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,0,0)
800754
newByteArray.inputStream().use {
801755
saveEntryCache(oldJarFileName,entryName,it)
802756
}

android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -323,36 +323,14 @@ class CompileAndroidAopTask(
323323
val byteArray = inputs.readAllBytes()
324324
if (byteArray.isNotEmpty()){
325325
try {
326-
val cr = ClassReader(byteArray)
327-
val cw = ClassWriter(cr,0)
328-
var thisHasStaticClock = false
329-
val cv = object : ReplaceBaseClassVisitor(cw) {
330-
override fun visitMethod(
331-
access: Int,
332-
name: String,
333-
descriptor: String,
334-
signature: String?,
335-
exceptions: Array<String?>?
336-
): MethodVisitor? {
337-
val mv = super.visitMethod(
338-
access,
339-
name,
340-
descriptor,
341-
signature,
342-
exceptions
343-
)
344-
thisHasStaticClock = isHasStaticClock
345-
return ReplaceInvokeMethodVisitor(mv,clazzName,oldSuperName)
346-
}
347-
}
348-
cr.accept(cv, 0)
349-
350-
if (!thisHasStaticClock){
351-
WovenIntoCode.wovenStaticCode(cw, thisClassName)
352-
}
353-
326+
// val newByteArray = try {
327+
// aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,WovenInfoUtils.getWovenClassWriterFlags(),WovenInfoUtils.getWovenParsingOptions())
328+
// } catch (e: Exception) {
329+
// aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,WovenInfoUtils.getWovenClassWriterFlags2(),WovenInfoUtils.getWovenParsingOptions2())
330+
// }
331+
val newByteArray = aopTaskUtils.wovenIntoCodeForCollect(thisClassName,byteArray,0,0)
354332
mkOutFile()
355-
cw.toByteArray().saveFile(outFile)
333+
newByteArray.saveFile(outFile)
356334
} catch (e: Exception) {
357335
e.printDetail()
358336
copy()

0 commit comments

Comments
 (0)