Ibotta / gradle-aspectj-pipeline-plugin

A Gradle plugin for Android projects which performs AspectJ weaving using Android's bytcode manipulation pipeline.
Apache License 2.0
75 stars 15 forks source link

IllegalStateException - not working with firebase/google play-service dependency. #5

Closed anandur91 closed 3 years ago

anandur91 commented 3 years ago

Plugin not working in a project with firebase/google play-service dependency.

Steps to reproduce:

Add below dependency and run the app implementation 'com.google.firebase:firebase-auth:20.0.3'

Actual Result: Run time error : Application class not found in dex path list AOP log error java.lang.IllegalStateException: Expecting .,<, or ;, but found - while unpacking <MessageType:Lcom/google/android/gms/internal/firebase-auth-api/zzaaa<TMessageType;TBuilderType;>;BuilderType:Lcom/google/android/gms/internal/firebase-auth-api/zzzw<TMessageType;TBuilderType;>;>Lcom/google/android/gms/internal/firebase-auth-api/zzyj<TMessageType;TBuilderType;>; at org.aspectj.util.GenericSignatureParser.parseClassTypeSignature(GenericSignatureParser.java:204) at org.aspectj.util.GenericSignatureParser.parseFieldTypeSignature(GenericSignatureParser.java:155) at org.aspectj.util.GenericSignatureParser.parseFormalTypeParameter(GenericSignatureParser.java:130) at org.aspectj.util.GenericSignatureParser.parseAsClassSignature(GenericSignatureParser.java:51) at org.aspectj.weaver.UnresolvedType.forGenericTypeSignature(UnresolvedType.java:275) at org.aspectj.weaver.bcel.BcelWorld.addSourceObjectType(BcelWorld.java:479) at org.aspectj.weaver.bcel.BcelWorld.addSourceObjectType(BcelWorld.java:453) at org.aspectj.weaver.bcel.BcelWeaver.addAspectsFromJarFile(BcelWeaver.java:265) at org.aspectj.weaver.bcel.BcelWeaver.addLibraryJarFile(BcelWeaver.java:238) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.initBcelWorld(AjBuildManager.java:878) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:253) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:189) at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:114) at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60) at org.aspectj.tools.ajc.Main.run(Main.java:371) at com.ibotta.gradle.aop.AspectJExecutor.execute(AspectJExecutor.kt:67) at com.ibotta.gradle.aop.AopWeaveTask.weave(AopWeaveTask.kt:70) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:49) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:42) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:726) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:693) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.run(ExecuteActionsTaskExecuter.java:569) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:395) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:387) at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:157) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:242) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:150) at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:84) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:554) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:537) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$300(ExecuteActionsTaskExecuter.java:108) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.executeWithPreviousOutputFiles(ExecuteActionsTaskExecuter.java:278) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:267) at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:33) at java.base/java.util.Optional.orElseGet(Optional.java:369) at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:33) at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26) at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:67) at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:36) at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:49) at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:34) at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:43) at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73) at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54) at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34) at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:44) at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:54) at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:38) at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49) at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:159) at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:72) at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:43) at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:44) at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:33) at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38) at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24) at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:92) at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:85) at java.base/java.util.Optional.map(Optional.java:265) at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55) at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:39) at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76) at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26) at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:94) at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49) at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:79) at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:53) at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:74) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:78) at java.base/java.util.Optional.orElseGet(Optional.java:369) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:78) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39) at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40) at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28) at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:194) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:186) at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:114) at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:409) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:399) at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:157) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:242) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:150) at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:94) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:356) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56) at java.base/java.lang.Thread.run(Thread.java:834)

vdelricco commented 3 years ago

Hi @anandur91!

Thanks for filing an issue.

I attempted to reproduce with the sample apps we've included in this project, but had no luck. I'm wondering if there are any extra steps to repro than simply including the dependency.

Since your issue is producing an AOP error log, perhaps you are attempting to annotate a method in your codebase that contains Firebase code?

Ideally we can add a small amount of code to the sample app and reproduce/isolate the issue.

anandur91 commented 3 years ago

Hi @vdelricco

Thanks for looking into this. Below added my code where all the time able to reproduce this

gradle-wrapper.properties

distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

project build.gradle

repositories {
        maven { url "https://plugins.gradle.org/m2/" }
    }

    dependencies {
        classpath "com.ibotta:plugin:1.1.0"
    }

app build.gradle

apply plugin: "com.ibotta.gradle.aop"

dependencies {
        implementation "org.aspectj:aspectjrt:1.9.6"
        implementation 'com.google.firebase:firebase-auth:20.0.3'
    }

AspectLogging class

@Aspect
class AOPLog {

    @Pointcut("within(com.example.aopdemo..*) && execution(* *(..))")
    fun allMethods() {
    }

    @Around("allMethods()")
    @Throws(Throwable::class)
    open fun onMethodAdvice(joinPoint: JoinPoint?): Any? {
        val methodSignature = joinPoint!!.signature as MethodSignature
        val methodName = methodSignature.name
        val startTime = System.currentTimeMillis();
        val result = (joinPoint as ProceedingJoinPoint).proceed()
        val endTime = System.currentTimeMillis() - startTime
        Log.e("LoggingVM", "$methodName ---> $endTime")
        return result
    }
}

Note: Firebase dependency is just added and not using anywhere in the demo app.

com.example.aopdemo package just have a launcher activity, and invoking some methods on onCreate method. It was tracking all the methods before firebase added. After adding, getting errors.

Also if you not able to reproduce the crash, please make sure, all new methods are getting tracked.

In an another big project, it was creating 113 dexes before adding plugin and it was 10 dexes after adding plugin. there i am getting the below aop log error java.lang.IllegalStateException: Expecting .,<, or ;, but found authapi while unpacking <R::Lcom/google/android/gms/common/api/Result;>Lcom/google/android/gms/common/api/internal/BaseImplementation$ApiMethodImpl<TR;Lcom/google/android/gms/internal/auth-api/zzr;>; at org.aspectj.util.GenericSignatureParser.parseClassTypeSignature(GenericSignatureParser.java:204)

Also is there any way for this plugin to support gradle 5.x

kriegaex commented 3 years ago

@vdelricco, actually @anandur91 asked about this problem on StackOverflow too and I wrote an answer which you might want to read, explaining why AspectJ has problems with unexpected hyphens in obfuscated package names and why your plugin might have problems which the Freefair plugin does not have due to your tight integration into the Android bytecode manipulation pipeline.

vdelricco commented 3 years ago

Thank you for the extra info @anandur91, we'll try some more things to reproduce the issue.

Also appreciate the extra extra info @kriegaex 😄 That's super interesting and will most likely come in very handy when we fix this.

Will come back to this thread when I have some more information to share.

vdelricco commented 3 years ago

Hi @anandur91, I believe I have a solution to your issue.

I was able to reproduce your issue within our included sample app by commenting out this line that sets a filter for our plugin.

Without specifying a filter, all of the classes on the classpath will be searched for aspect annotations, which is how we can create a problem by simply adding a dependency to the project.

For your issue, try adding a configuration block similar to the code in step 2 of the README.

I'm guessing it'll look something like this for your example project:

aopWeave {
    filter = "com/example/aopdemo"
}

Let me know if this works for you!

kriegaex commented 3 years ago

I do not even use Gradle, I build all my AspectJ applications with Maven. I just wanted to help the OP a bit here. Anyway, I have a few general questions with regard to filtering which are note explained anywhere here (I also searched for sample code throughout the repository):

Maybe you could document that.

BTW, I am still somewhat taken aback by the fact that the plugin takes aspect and target class search in its own hands instead of being able to specify that to the AspectJ compiler in the standard way via inpath and aspectpath. This is how other plugins and AspectJ itself do it.

eschlenz commented 3 years ago

@kriegaex

The filter option is documented in the project root readme. At this time, we have no immediate plans to expand the functionality of the filter. That's not to say we won't, we just haven't had a need up to this point.

Also, just a reminder, open source contributions are always welcome.

kriegaex commented 3 years ago

The filter option is documented in the project root readme.

Yeah, that's why the OP switched to another build plugin instead of using yours. The readme mentions the filter, but does not say that it is necessary because your plugin ignores pointcuts like within() or !within(), forcing users to specify them again as a build plugin filter, only with limited functionality, i.e. they cannot express the same filter criteria, only more unspecific ones. You should document it better, this is a real caveat because it is against how AspectJ compilation or weaving are supposed to work.

Furthermore, your readme does not answer the questions I asked about the filter above. You did not answer them either. That you have no plans to expand the functionality does not tell me what exactly the current functionality encompasses.

Also, just a reminder, open source contributions are always welcome.

Like I said, I use Maven. Gradle is not my world. I just want to facilitate here because I know more about AspectJ than the OP. I contribute to AspectJ Maven, to AspectJ itself and answer lots of AOP-related questions on StackOverflow. I cannot do everything, otherwise there is no time left for my daytime job. ;-)

eschlenz commented 3 years ago

Thanks for the feedback.