diff --git a/CHANGELOG.md b/CHANGELOG.md index ecd3b4d..9711b0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ # Change Log +### Version 0.1.8 +- improve compatibility +- optimize hook proguard +- add checkIncrementalInDebug +- fix npe cased by refer-checker +- ### Version 0.1.7 - Optimize incremental build and fix bugs - Fix memory leak in plugins diff --git a/GradleToolKit/src/main/kotlin/com/ss/android/ugc/bytex/gradletoolkit/MergeResources.kt b/GradleToolKit/src/main/kotlin/com/ss/android/ugc/bytex/gradletoolkit/MergeResources.kt index dee6f63..3e4ace6 100644 --- a/GradleToolKit/src/main/kotlin/com/ss/android/ugc/bytex/gradletoolkit/MergeResources.kt +++ b/GradleToolKit/src/main/kotlin/com/ss/android/ugc/bytex/gradletoolkit/MergeResources.kt @@ -5,20 +5,20 @@ package com.ss.android.ugc.bytex.gradletoolkit */ import com.android.build.gradle.tasks.MergeResources -import com.android.ide.common.resources.ResourceSet import java.io.File +//todo fix reflection fun MergeResources.resourceSetList(): List { val resourceSets = try { resourceSetList1() } catch (e: Exception) { resourceSetList2() } - return resourceSets.flatMap { it.sourceFiles }.toSet().toList() + return resourceSets.flatMap { it!!.javaClass.getMethod("getSourceFiles").invoke(it) as List }.toSet().toList() } -fun MergeResources.resourceSetList1(): Iterable { +private fun MergeResources.resourceSetList1(): Iterable<*> { val computeResourceSetListMethod = MergeResources::class.java.declaredMethods .find { it.name == "computeResourceSetList" && it.parameterCount == 0 }!! @@ -26,13 +26,13 @@ fun MergeResources.resourceSetList1(): Iterable { val oldIsAccessible = computeResourceSetListMethod.isAccessible try { computeResourceSetListMethod.isAccessible = true - return computeResourceSetListMethod.invoke(this) as Iterable + return computeResourceSetListMethod.invoke(this) as Iterable<*> } finally { computeResourceSetListMethod.isAccessible = oldIsAccessible } } -fun MergeResources.resourceSetList2(): Iterable { +private fun MergeResources.resourceSetList2(): Iterable<*> { val getConfiguredResourceSets = MergeResources::class.java.declaredMethods .find { it.name == "getConfiguredResourceSets" && it.parameterCount == 1 }!! @@ -44,7 +44,7 @@ fun MergeResources.resourceSetList2(): Iterable { try { getConfiguredResourceSets.isAccessible = true getPreprocessor.isAccessible = true - return getConfiguredResourceSets.invoke(this, getPreprocessor.invoke(this)) as Iterable + return getConfiguredResourceSets.invoke(this, getPreprocessor.invoke(this)) as Iterable<*> } finally { getConfiguredResourceSets.isAccessible = getConfiguredResourceSetsAccess getPreprocessor.isAccessible = getPreprocessorAccess diff --git a/HookProguard/ProguardConfigurationResolver/.gitignore b/HookProguard/ProguardConfigurationResolver/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/HookProguard/ProguardConfigurationResolver/build.gradle b/HookProguard/ProguardConfigurationResolver/build.gradle new file mode 100644 index 0000000..14c1800 --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/build.gradle @@ -0,0 +1,7 @@ +apply plugin: 'java' +group "$upload_group" +version "$upload_version" +apply from: rootProject.file('gradle/publish.gradle') +dependencies { + compileOnly gradleApi() +} \ No newline at end of file diff --git a/HookProguard/ProguardConfigurationResolver/gradle.properties b/HookProguard/ProguardConfigurationResolver/gradle.properties new file mode 100644 index 0000000..ddf95ae --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/gradle.properties @@ -0,0 +1,2 @@ +ARTIFACT_GROUP=com.bytedance.android.byteX +ARTIFACT_NAME=ProguardConfigurationResolver diff --git a/HookProguard/ProguardConfigurationResolver/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/ProguardConfigurationResolver.java b/HookProguard/ProguardConfigurationResolver/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/ProguardConfigurationResolver.java new file mode 100644 index 0000000..f01ad0a --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/ProguardConfigurationResolver.java @@ -0,0 +1,27 @@ +package com.ss.android.ugc.bytex.proguardconfigurationresolver; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; + +import javax.annotation.Nullable; + +/** + * Created by yangzhiqian on 2020/7/6
+ */ +public abstract class ProguardConfigurationResolver { + protected Project project; + protected String variantName; + + public ProguardConfigurationResolver(Project project, String variantName) { + this.project = project; + this.variantName = variantName; + } + + @Nullable + public abstract Task getTask(); + + @Nullable + public abstract FileCollection getAllConfigurationFiles(); +} + diff --git a/HookProguard/ProguardConfigurationResolver/task/.gitignore b/HookProguard/ProguardConfigurationResolver/task/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/task/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/HookProguard/ProguardConfigurationResolver/task/build.gradle b/HookProguard/ProguardConfigurationResolver/task/build.gradle new file mode 100644 index 0000000..2a4fc3b --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/task/build.gradle @@ -0,0 +1,11 @@ +apply plugin: 'java' +group "$upload_group" +version "$upload_version" + +dependencies { + compileOnly gradleApi() + compileOnly "com.android.tools.build:gradle:3.6.2" + implementation project(":ProguardConfigurationResolver") +} + +apply from: rootProject.file('gradle/publish.gradle') \ No newline at end of file diff --git a/HookProguard/ProguardConfigurationResolver/task/gradle.properties b/HookProguard/ProguardConfigurationResolver/task/gradle.properties new file mode 100644 index 0000000..28dc380 --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/task/gradle.properties @@ -0,0 +1,2 @@ +ARTIFACT_GROUP=com.bytedance.android.byteX +ARTIFACT_NAME=ProguardConfigurationResolver-task diff --git a/HookProguard/ProguardConfigurationResolver/task/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/task/ProguardConfigurableTaskResolver.java b/HookProguard/ProguardConfigurationResolver/task/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/task/ProguardConfigurableTaskResolver.java new file mode 100644 index 0000000..c4e4dc4 --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/task/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/task/ProguardConfigurableTaskResolver.java @@ -0,0 +1,40 @@ +package com.ss.android.ugc.bytex.proguardconfigurationresolver.task; + +import com.android.build.gradle.internal.tasks.ProguardConfigurableTask; +import com.android.build.gradle.internal.tasks.ProguardTask; +import com.android.build.gradle.internal.tasks.R8Task; +import com.ss.android.ugc.bytex.proguardconfigurationresolver.ProguardConfigurationResolver; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; + +/** + * Created by yangzhiqian on 2020/7/6
+ */ +public class ProguardConfigurableTaskResolver extends ProguardConfigurationResolver { + + public ProguardConfigurableTaskResolver(Project project, String variantName) { + super(project, variantName); + } + + @Override + public Task getTask() { + for (Task task : project.getTasks()) { + if ((task instanceof ProguardTask || task instanceof R8Task) && + ((ProguardConfigurableTask) task).getVariantName().equals(variantName)) { + return task; + } + } + return null; + } + + @Override + public FileCollection getAllConfigurationFiles() { + Task task = getTask(); + if (task == null) { + return null; + } + return ((ProguardConfigurableTask) getTask()).getConfigurationFiles(); + } +} diff --git a/HookProguard/ProguardConfigurationResolver/transform/.gitignore b/HookProguard/ProguardConfigurationResolver/transform/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/transform/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/HookProguard/ProguardConfigurationResolver/transform/build.gradle b/HookProguard/ProguardConfigurationResolver/transform/build.gradle new file mode 100644 index 0000000..4ccc138 --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/transform/build.gradle @@ -0,0 +1,11 @@ +apply plugin: 'java' +group "$upload_group" +version "$upload_version" + +dependencies { + compileOnly gradleApi() + compileOnly "com.android.tools.build:gradle:3.5.3" + implementation project(":ProguardConfigurationResolver") +} + +apply from: rootProject.file('gradle/publish.gradle') \ No newline at end of file diff --git a/HookProguard/ProguardConfigurationResolver/transform/gradle.properties b/HookProguard/ProguardConfigurationResolver/transform/gradle.properties new file mode 100644 index 0000000..7b9efd7 --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/transform/gradle.properties @@ -0,0 +1,2 @@ +ARTIFACT_GROUP=com.bytedance.android.byteX +ARTIFACT_NAME=ProguardConfigurationResolver-transform diff --git a/HookProguard/ProguardConfigurationResolver/transform/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/transform/ProguardConfigurableTransformResolver.java b/HookProguard/ProguardConfigurationResolver/transform/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/transform/ProguardConfigurableTransformResolver.java new file mode 100644 index 0000000..232d82f --- /dev/null +++ b/HookProguard/ProguardConfigurationResolver/transform/src/main/java/com/ss/android/ugc/bytex/proguardconfigurationresolver/transform/ProguardConfigurableTransformResolver.java @@ -0,0 +1,53 @@ +package com.ss.android.ugc.bytex.proguardconfigurationresolver.transform; + +import com.android.build.gradle.internal.pipeline.TransformTask; +import com.android.build.gradle.internal.transforms.ProguardConfigurable; +import com.ss.android.ugc.bytex.proguardconfigurationresolver.ProguardConfigurationResolver; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; + +import java.lang.reflect.Method; + +/** + * Created by yangzhiqian on 2020/7/6
+ */ +public class ProguardConfigurableTransformResolver extends ProguardConfigurationResolver { + + public ProguardConfigurableTransformResolver(Project project, String variantName) { + super(project, variantName); + } + + @Override + public Task getTask() { + for (Task task : project.getTasks()) { + if (task instanceof TransformTask) { + TransformTask transformTask = (TransformTask) task; + String name = transformTask.getTransform().getClass().getName(); + if (transformTask.getVariantName().equals(variantName) && + ("com.android.build.gradle.internal.transforms.ProGuardTransform".equals(name) || + "com.android.build.gradle.internal.transforms.R8Transform".equals(name))) { + return task; + } + } + } + return null; + } + + @Override + public FileCollection getAllConfigurationFiles() { + Task task = getTask(); + if (task == null) { + return null; + } + ProguardConfigurable proguardConfigurable = (ProguardConfigurable) ((TransformTask) task).getTransform(); + try { + Method method = ProguardConfigurable.class.getDeclaredMethod("getAllConfigurationFiles"); + method.setAccessible(true); + return (FileCollection) method.invoke(proguardConfigurable); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/HookProguard/build.gradle b/HookProguard/build.gradle index 388de92..dae27ae 100644 --- a/HookProguard/build.gradle +++ b/HookProguard/build.gradle @@ -1 +1,6 @@ -apply from: rootProject.file('gradle/plugin.gradle') \ No newline at end of file +apply from: rootProject.file('gradle/plugin.gradle') +dependencies { + implementation project(':ProguardConfigurationResolver') + implementation project(':ProguardConfigurationResolver-task') + implementation project(':ProguardConfigurationResolver-transform') +} \ No newline at end of file diff --git a/HookProguard/src/main/java/com/ss/android/ugc/bytex/hookproguard/ProguardConfigurationAnalyzer.java b/HookProguard/src/main/java/com/ss/android/ugc/bytex/hookproguard/ProguardConfigurationAnalyzer.java index 63b16ae..216eb0f 100644 --- a/HookProguard/src/main/java/com/ss/android/ugc/bytex/hookproguard/ProguardConfigurationAnalyzer.java +++ b/HookProguard/src/main/java/com/ss/android/ugc/bytex/hookproguard/ProguardConfigurationAnalyzer.java @@ -7,13 +7,10 @@ import com.android.build.gradle.LibraryExtension; import com.android.build.gradle.LibraryPlugin; import com.android.build.gradle.api.BaseVariant; -import com.android.build.gradle.internal.pipeline.TransformTask; -import com.android.build.gradle.internal.transforms.ProGuardTransform; -import com.android.build.gradle.internal.transforms.ProguardConfigurable; -import com.android.build.gradle.internal.transforms.R8Transform; import com.ss.android.ugc.bytex.common.configuration.BooleanProperty; import com.ss.android.ugc.bytex.common.graph.Graph; import com.ss.android.ugc.bytex.common.graph.Node; +import com.ss.android.ugc.bytex.proguardconfigurationresolver.ProguardConfigurationResolver; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -24,9 +21,9 @@ import org.jetbrains.annotations.NotNull; import java.io.File; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -293,38 +290,26 @@ private static class ProguardConfigurationWithVariantAnalyzer { // specification with the class hierarchy private final List classHierarchySpecifications = new ArrayList<>(); private final Map configurationFiles = new HashMap<>(); - private ProguardConfigurable proGuardTransform; + private final ProguardConfigurationResolver configurationResolver; private boolean valid = false; ProguardConfigurationWithVariantAnalyzer(Project project, String variantName, Set dependenciesRunBeforeTasks, boolean verify) { super(); - Task hookTask = null; - for (Task task : project.getTasks()) { - if (task instanceof TransformTask) { - TransformTask transformTask = (TransformTask) task; - if (transformTask.getVariantName().equals(variantName) && (transformTask.getTransform() instanceof ProGuardTransform || transformTask.getTransform() instanceof R8Transform)) { - hookTask = task; - proGuardTransform = (ProguardConfigurable) transformTask.getTransform(); - FileCollection fileCollection = getAllConfigurationFileCollection(); - String capitalVariantName = variantName.substring(0, 1).toUpperCase() + variantName.substring(1); - dependenciesRunBeforeTasks.stream() - .map(s -> task.getProject().getTasks().findByName(s + capitalVariantName)) - .filter(Objects::nonNull) - .forEach(t -> t.dependsOn(fileCollection)); - if (verify) { - task.doFirst(task1 -> verifyProguardConfiguration()); - task.doLast(task12 -> verifyProguardConfiguration()); - } - } - } - } - final Task hTask = hookTask; + configurationResolver = ProguardConfigurationResolverFactory.createProguardConfigurationResolver(project, variantName); + Task hookTask = configurationResolver.getTask(); if (hookTask != null) { + String capitalVariantName = variantName.substring(0, 1).toUpperCase() + variantName.substring(1); + dependenciesRunBeforeTasks.stream() + .map(s -> hookTask.getProject().getTasks().findByName(s + capitalVariantName)) + .filter(Objects::nonNull) + .forEach(t -> t.dependsOn(configurationResolver.getAllConfigurationFiles())); + if (verify) { + hookTask.doFirst(task1 -> verifyProguardConfiguration()); + hookTask.doLast(task12 -> verifyProguardConfiguration()); + } project.getGradle() .getTaskGraph() - .whenReady(taskExecutionGraph -> valid = taskExecutionGraph.hasTask(hTask)); - } else { - project.getLogger().warn("Can not find proguard task for " + variantName); + .whenReady(taskExecutionGraph -> valid = taskExecutionGraph.hasTask(hookTask)); } } @@ -387,26 +372,17 @@ synchronized void prepare() { } private List getAllConfigurationFiles() { + FileCollection allConfigurationFiles = configurationResolver.getAllConfigurationFiles(); + if (allConfigurationFiles == null) { + return Collections.emptyList(); + } List allFiles = new LinkedList<>(); - for (File file : getAllConfigurationFileCollection()) { + for (File file : allConfigurationFiles) { allFiles.add(file); } return allFiles; } - private FileCollection getAllConfigurationFileCollection() { - if (proGuardTransform == null) { - throw new RuntimeException("This plugin can only be applied in release build or when proguard is enabled."); - } - try { - Method method = ProguardConfigurable.class.getDeclaredMethod("getAllConfigurationFiles"); - method.setAccessible(true); - return (FileCollection) method.invoke(proGuardTransform); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - private void filterAndSplit(Configuration configuration) { if (configuration.keep == null) return; List newKeepList = new ArrayList<>(); diff --git a/HookProguard/src/main/java/com/ss/android/ugc/bytex/hookproguard/ProguardConfigurationResolverFactory.java b/HookProguard/src/main/java/com/ss/android/ugc/bytex/hookproguard/ProguardConfigurationResolverFactory.java new file mode 100644 index 0000000..7142e04 --- /dev/null +++ b/HookProguard/src/main/java/com/ss/android/ugc/bytex/hookproguard/ProguardConfigurationResolverFactory.java @@ -0,0 +1,23 @@ +package com.ss.android.ugc.bytex.hookproguard; + +import com.android.builder.model.Version; +import com.android.repository.Revision; +import com.ss.android.ugc.bytex.proguardconfigurationresolver.ProguardConfigurationResolver; +import com.ss.android.ugc.bytex.proguardconfigurationresolver.task.ProguardConfigurableTaskResolver; +import com.ss.android.ugc.bytex.proguardconfigurationresolver.transform.ProguardConfigurableTransformResolver; + +import org.gradle.api.Project; + +/** + * Created by yangzhiqian on 2020/7/27
+ */ +class ProguardConfigurationResolverFactory { + public static ProguardConfigurationResolver createProguardConfigurationResolver(Project project, String variantName) { + Revision revision = Revision.parseRevision(Version.ANDROID_GRADLE_PLUGIN_VERSION); + if (revision.getMajor() >= 3 && revision.getMinor() >= 6) { + return new ProguardConfigurableTaskResolver(project, variantName); + } else { + return new ProguardConfigurableTransformResolver(project, variantName); + } + } +} diff --git a/README.md b/README.md index d5816be..471eced 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Add those configuration code to your build.gradle, and apply your plugins on dem ```groovy buildscript { - ext.plugin_version="0.1.7" + ext.plugin_version="0.1.8" repositories { google() jcenter() diff --git a/README_zh.md b/README_zh.md index 0be2e11..2fec0f0 100644 --- a/README_zh.md +++ b/README_zh.md @@ -65,7 +65,7 @@ ByteX是一个基于gradle transform api和ASM的字节码插件平台(或许 ```groovy buildscript { - ext.plugin_version="0.1.7" + ext.plugin_version="0.1.8" repositories { google() jcenter() diff --git a/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformInputs.kt b/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformInputs.kt index 127573f..d2a52d4 100644 --- a/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformInputs.kt +++ b/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformInputs.kt @@ -3,8 +3,6 @@ package com.ss.android.ugc.bytex.transformer import com.android.build.api.transform.Status import com.android.build.api.transform.TransformInput import com.android.build.api.transform.TransformInvocation -import com.android.build.gradle.internal.utils.toImmutableList -import com.android.build.gradle.internal.utils.toImmutableMap import com.google.common.collect.Streams import com.google.gson.GsonBuilder import com.google.gson.TypeAdapter @@ -69,7 +67,7 @@ class TransformInputs internal constructor(private val context: TransformContext }.forEach { map[it.parent] = it.items.toSet() } - map.toImmutableMap() + Collections.unmodifiableMap(map) } finally { //用完即删 cacheFile.delete() @@ -86,7 +84,7 @@ class TransformInputs internal constructor(private val context: TransformContext } } } - inputs.toImmutableMap() + Collections.unmodifiableMap(inputs) } val changedFiles by lazy { @@ -206,7 +204,7 @@ class TransformInputs internal constructor(private val context: TransformContext } } `in`.endObject() - return Entry(parent!!, items!!.toImmutableList()) + return Entry(parent!!, Collections.unmodifiableList(items!!)) } } } diff --git a/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformOutputs.kt b/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformOutputs.kt index 91459d5..dcf8600 100644 --- a/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformOutputs.kt +++ b/TransformEngine/src/main/java/com/ss/android/ugc/bytex/transformer/TransformOutputs.kt @@ -2,8 +2,6 @@ package com.ss.android.ugc.bytex.transformer import com.android.build.api.transform.* import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.utils.toImmutableList -import com.android.build.gradle.internal.utils.toImmutableMap import com.google.common.hash.Hashing import com.google.common.io.Files import com.google.gson.GsonBuilder @@ -72,7 +70,7 @@ class TransformOutputs internal constructor(private val context: TransformContex for (entry in it) { map[entry.path] = entry } - map.toImmutableMap() + Collections.unmodifiableMap(map) } } finally { //用完即删 @@ -187,7 +185,7 @@ class TransformOutputs internal constructor(private val context: TransformContex items.add(it.outputEntry("$parent/$relativePath")) } items.sort() - items.toImmutableList() + Collections.unmodifiableList(items) } val hash = if (status == Status.REMOVED || bytes == null || bytes.isEmpty()) { INVALID_HASH @@ -247,7 +245,7 @@ class TransformOutputs internal constructor(private val context: TransformContex } } `in`.endObject() - return Entry(input, path!!, hash, items.toImmutableList()) + return Entry(input, path!!, hash, Collections.unmodifiableList(items)) } } diff --git a/base-plugin/src/main/java/com/ss/android/ugc/bytex/base/ByteXTransform.java b/base-plugin/src/main/java/com/ss/android/ugc/bytex/base/ByteXTransform.java index 71a6395..6722e0f 100644 --- a/base-plugin/src/main/java/com/ss/android/ugc/bytex/base/ByteXTransform.java +++ b/base-plugin/src/main/java/com/ss/android/ugc/bytex/base/ByteXTransform.java @@ -1,10 +1,12 @@ package com.ss.android.ugc.bytex.base; +import com.android.build.api.transform.TransformException; +import com.android.build.api.transform.TransformInvocation; import com.ss.android.ugc.bytex.common.CommonTransform; import com.ss.android.ugc.bytex.common.IPlugin; -import com.ss.android.ugc.bytex.common.log.LevelLog; import com.ss.android.ugc.bytex.transformer.TransformContext; +import java.io.IOException; import java.util.Collections; import java.util.List; @@ -34,6 +36,12 @@ public boolean shouldSaveCache() { return context.extension.isShouldSaveCache() && super.shouldSaveCache(); } + @Override + protected void afterTransform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException { + super.afterTransform(transformInvocation); + context.releaseContext(); + } + @Override protected List getPlugins() { if (!context.extension.isEnable()) { diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/AbsPlugin.java b/common/src/main/java/com/ss/android/ugc/bytex/common/AbsPlugin.java index f6a92c8..e702443 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/AbsPlugin.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/AbsPlugin.java @@ -3,6 +3,7 @@ import com.android.build.api.transform.Transform; import com.android.build.gradle.AppExtension; import com.google.common.reflect.TypeToken; +import com.ss.android.ugc.bytex.common.configuration.BooleanProperty; import com.ss.android.ugc.bytex.common.configuration.ProjectOptions; import com.ss.android.ugc.bytex.common.exception.GlobalWhiteListManager; import com.ss.android.ugc.bytex.common.hook.TransformHook; @@ -21,6 +22,7 @@ public abstract class AbsPlugin implements Plugin(new BaseContext<>(project, android, extension), this); @@ -41,6 +43,11 @@ public boolean alone() { return alone; } + @Override + public boolean isRunningAlone() { + return isRunningAlone; + } + @Override public boolean shouldSaveCache() { return extension.isShouldSaveCache() && transformConfiguration().isIncremental(); @@ -62,6 +69,13 @@ public final void apply(@NotNull Project project) { project.getExtensions().add(extension.getName(), extension); } onApply(project); + if (BooleanProperty.CHECK_INCREMENTAL_INDEBUG.value()) { + project.afterEvaluate(p -> { + if (!transformConfiguration().isIncremental() && extension.isEnableInDebug()) { + throw new IllegalStateException("ByteX plugin " + extension.getName() + " does not support incremental"); + } + }); + } String hookTransformName = hookTransformName(); if (hookTransformName != null) { TransformHook.inject(project, android, this); @@ -70,11 +84,14 @@ public final void apply(@NotNull Project project) { try { ByteXExtension byteX = project.getExtensions().getByType(ByteXExtension.class); byteX.registerPlugin(this); + isRunningAlone = false; } catch (UnknownDomainObjectException e) { android.registerTransform(getTransform()); + isRunningAlone = true; } } else { android.registerTransform(getTransform()); + isRunningAlone = true; } } } diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/BaseContext.java b/common/src/main/java/com/ss/android/ugc/bytex/common/BaseContext.java index 2540dda..4b2d37f 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/BaseContext.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/BaseContext.java @@ -41,6 +41,27 @@ public synchronized void init() { return; } logger = createLogger(); + synchronized (cachedLogger) { + cachedLogger.accept((logTime, level, prefix, msg, t) -> { + switch (level) { + case DEBUG: + logger.d(prefix, msg); + break; + case INFO: + logger.i(prefix, msg); + break; + case WARN: + logger.w(prefix, msg, t); + break; + case ERROR: + logger.e(prefix, msg, t); + break; + default: + throw new IllegalArgumentException(level.toString()); + } + }); + cachedLogger.clear(); + } getLogger().i("init"); } @@ -63,28 +84,6 @@ protected ILogger createLogger() { LevelLog levelLog = new LevelLog(logDistributor); levelLog.setLevel(extension.getLogLevel()); levelLog.setTag(extension.getName()); - - synchronized (cachedLogger) { - cachedLogger.accept((logTime, level, prefix, msg, t) -> { - switch (level) { - case DEBUG: - levelLog.d(prefix, msg); - break; - case INFO: - levelLog.i(prefix, msg); - break; - case WARN: - levelLog.w(prefix, msg, t); - break; - case ERROR: - levelLog.e(prefix, msg, t); - break; - default: - throw new IllegalArgumentException(level.toString()); - } - }); - cachedLogger.clear(); - } return levelLog; } diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/CommonTransform.java b/common/src/main/java/com/ss/android/ugc/bytex/common/CommonTransform.java index 4181467..d29117f 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/CommonTransform.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/CommonTransform.java @@ -203,7 +203,6 @@ public final synchronized void transform(TransformInvocation transformInvocation LevelLog.sDefaultLogger.e("do afterExecute", throwable); } } - context.releaseContext(); transformContext.release(); timer.record("Total cost time = [%s ms]"); if (BooleanProperty.ENABLE_HTML_LOG.value()) { @@ -222,7 +221,6 @@ protected void afterTransform(TransformInvocation transformInvocation) throws Tr } protected void init(TransformContext transformContext) { - context.setTransformContext(transformContext); LevelLog.sDefaultLogger = context.getLogger(); if (BooleanProperty.ENABLE_HTML_LOG.value()) { String applicationId = "unknow"; diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/IPlugin.java b/common/src/main/java/com/ss/android/ugc/bytex/common/IPlugin.java index 03238e5..12225bc 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/IPlugin.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/IPlugin.java @@ -17,11 +17,19 @@ public interface IPlugin { boolean enable(TransformContext transformContext); /** - * 是否用alone模式,即形成单独的transform。 + * 是否用alone模式,即形成单独的transform * if alone, it will make your plugin as a single transform. */ boolean alone(); + + /** + * 是否会alone形成单独的transform运行。{@link #alone()}表示配置状态,{@link #isRunningAlone()}表示结果 + * Whether it will run in a single transform alone. {@link #alone()} indicates that plugin wants + * run alone, {@link #isRunningAlone()} indicates that plugin will run alone. + */ + boolean isRunningAlone(); + @Nonnull default TransformConfiguration transformConfiguration() { return TransformConfiguration.DEFAULT; diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/configuration/BooleanProperty.java b/common/src/main/java/com/ss/android/ugc/bytex/common/configuration/BooleanProperty.java index eed8ac6..d7a769e 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/configuration/BooleanProperty.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/configuration/BooleanProperty.java @@ -9,8 +9,10 @@ public enum BooleanProperty implements Property { ENABLE_DUPLICATE_CLASS_CHECK("bytex.enableDuplicateClassCheck", true), ENABLE_HTML_LOG("bytex.enableHtmlLog", true), ENABLE_RAM_CACHE("bytex.enableRAMCache", true), - ENABLE_ASYNC_CACHE("bytex.asyncSaveCache", true), - ENABLE_VERIFY_PROGUARD_CONFIGURATION_CHANGED("bytex.verifyProguardConfigurationChanged", true); + ENABLE_ASYNC_LOAD_CACHE("bytex.asyncLoadCache", true), + ENABLE_ASYNC_SAVE_CACHE("bytex.asyncSaveCache", true), + ENABLE_VERIFY_PROGUARD_CONFIGURATION_CHANGED("bytex.verifyProguardConfigurationChanged", true), + CHECK_INCREMENTAL_INDEBUG("bytex.checkIncrementalInDebug", false); @NonNull private final String propertyName; diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/GraphBuilder.java b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/GraphBuilder.java index 3e52503..4479bad 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/GraphBuilder.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/GraphBuilder.java @@ -30,9 +30,27 @@ public boolean isCacheValid() { return false; } - // thread safe public void add(ClassEntity entity) { + add(entity, false); + } + + // thread safe + public void add(ClassEntity entity, boolean fromCache) { Node current = getOrPutEmpty((entity.access & Opcodes.ACC_INTERFACE) != 0, entity.name); + if (!current.defined.compareAndSet(false, true)) { + if (fromCache) { + //先正式添加后面再添加cache,防止cache覆盖了新的数据,此处return + return; + } + if (!entity.fromAndroid && !isCacheValid()) { + String msg = String.format("We found duplicate %s class files in the project.", current.entity.name); + if (BooleanProperty.ENABLE_DUPLICATE_CLASS_CHECK.value()) { + throw new DuplicateClassException(msg); + } else { + LevelLog.sDefaultLogger.e(msg); + } + } + } ClassNode superNode = null; List interfaceNodes = Collections.emptyList(); @@ -56,14 +74,6 @@ public void add(ClassEntity entity) { }) .collect(Collectors.toList()); } - if (!current.defined.compareAndSet(false, true) && !entity.fromAndroid && !isCacheValid()) { - String msg = String.format("We found duplicate %s class files in the project.", current.entity.name); - if (BooleanProperty.ENABLE_DUPLICATE_CLASS_CHECK.value()) { - throw new DuplicateClassException(msg); - } else { - LevelLog.sDefaultLogger.e(msg); - } - } current.entity = entity; current.parent = superNode; current.interfaces = interfaceNodes; diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/IGraphCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/IGraphCache.kt deleted file mode 100644 index 790124b..0000000 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/IGraphCache.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.ss.android.ugc.bytex.common.graph; - -/** - * Created by yangzhiqian on 2019-12-01
- */ -interface IGraphCache { - - fun loadCache(t: T?, graphBuilder: GraphBuilder): Boolean - - fun saveCache(t: T?, graph: Graph): Boolean -} diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/AsynchronousGraphCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/AsynchronousGraphCache.kt new file mode 100644 index 0000000..42f5436 --- /dev/null +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/AsynchronousGraphCache.kt @@ -0,0 +1,19 @@ +package com.ss.android.ugc.bytex.common.graph.cache + +import com.ss.android.ugc.bytex.common.graph.Graph +import com.ss.android.ugc.bytex.transformer.concurrent.Schedulers +import java.util.concurrent.Future + +/** + * Created by yangzhiqian on 2020/7/12
+ */ +class AsynchronousGraphCache(realCache: IGraphCache) : IGraphCache by realCache { + + fun loadCacheAsync(t: T?, graphBuilder: CachedGraphBuilder): Future { + return Schedulers.IO().submit { loadCache(t, graphBuilder) } + } + + fun saveCacheAsync(t: T?, graph: Graph): Future { + return Schedulers.IO().submit { saveCache(t, graph) } + } +} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/CachedGraphBuilder.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/CachedGraphBuilder.kt index 2cfc6e3..6d3cea4 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/CachedGraphBuilder.kt +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/CachedGraphBuilder.kt @@ -1,26 +1,63 @@ package com.ss.android.ugc.bytex.common.graph.cache; +import com.ss.android.ugc.bytex.common.configuration.BooleanProperty import com.ss.android.ugc.bytex.common.graph.Graph import com.ss.android.ugc.bytex.common.graph.GraphBuilder import java.io.File +import java.util.concurrent.Future class CachedGraphBuilder(private val graphCacheFile: File?, shouldLoadCache: Boolean, private val shouldSaveCache: Boolean) : GraphBuilder() { - private val fileGraphCacheHandler = GraphCacheFactory.createFileGraphCacheHandler() - private val isCacheValid = shouldLoadCache && fileGraphCacheHandler.loadCache(graphCacheFile, this) - - init { - graphCacheFile?.delete() - if (graphCacheFile != null) { - RAMGraphCache.clearCache(graphCacheFile) - } - } + private val graphCache = + AsynchronousGraphCache( + DefaultGraphCache( + GsonClassesCache( + if (BooleanProperty.ENABLE_RAM_CACHE.value()) { + RAMClassesCache + } else { + null + } + ) + ) + ) + private var grapCacheFuture: Future? = null + private val isCacheValid = + shouldLoadCache && + if (BooleanProperty.ENABLE_ASYNC_LOAD_CACHE.value()) { + grapCacheFuture = graphCache.loadCacheAsync(graphCacheFile, this) + true + } else { + graphCache.loadCache(graphCacheFile, this).apply { + graphCacheFile?.delete() + if (graphCacheFile != null) { + RAMClassesCache.clearCache(graphCacheFile) + } + if (!this) { + throw IllegalStateException("Failed to load cache") + } + } + } override fun isCacheValid(): Boolean = isCacheValid + @Synchronized override fun build(): Graph { + //先保证cache执行完成 + grapCacheFuture?.get()?.apply { + graphCacheFile?.delete() + if (graphCacheFile != null) { + RAMClassesCache.clearCache(graphCacheFile) + } + if (!this) { + throw IllegalStateException("Failed to load cache") + } + } val graph = super.build() if (shouldSaveCache) { - fileGraphCacheHandler.saveCache(graphCacheFile, graph) + if (BooleanProperty.ENABLE_ASYNC_SAVE_CACHE.value()) { + graphCache.saveCacheAsync(graphCacheFile, graph) + } else { + graphCache.saveCache(graphCacheFile, graph) + } } return graph } diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/DefaultGraphCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/DefaultGraphCache.kt new file mode 100644 index 0000000..c228305 --- /dev/null +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/DefaultGraphCache.kt @@ -0,0 +1,24 @@ +package com.ss.android.ugc.bytex.common.graph.cache + +import com.ss.android.ugc.bytex.common.graph.Graph +import java.io.File +import java.util.stream.Collectors + +/** + * Created by yangzhiqian on 2020/7/13
+ */ +class DefaultGraphCache(private val classCache: IClassCache) : IGraphCache { + override fun loadCache(t: File?, graphBuilder: CachedGraphBuilder): Boolean { + val cache = classCache.loadCache(t) ?: return false + //经过抖音cache测试性能,结果多线程方案差不多,但大约结果是 + //Schedulers.COMPUTATION().submitAndAwait node.entity }.collect(Collectors.toList())) + } +} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GraphCacheFactory.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GraphCacheFactory.kt deleted file mode 100644 index c49960a..0000000 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GraphCacheFactory.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.ss.android.ugc.bytex.common.graph.cache - -import com.ss.android.ugc.bytex.common.configuration.BooleanProperty -import com.ss.android.ugc.bytex.common.graph.IGraphCache -import java.io.File - -/** - * Created by yangzhiqian on 2019-12-01
- */ -object GraphCacheFactory { - fun createFileGraphCacheHandler(): IGraphCache { - return GsonGraphCache.apply { - asyncSaveCache = BooleanProperty.ENABLE_ASYNC_CACHE.value() - useRamCache(BooleanProperty.ENABLE_RAM_CACHE.value()) - } - } -} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GsonClassesCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GsonClassesCache.kt new file mode 100644 index 0000000..d6b6675 --- /dev/null +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GsonClassesCache.kt @@ -0,0 +1,62 @@ +package com.ss.android.ugc.bytex.common.graph.cache + +import com.google.gson.GsonBuilder +import com.google.gson.reflect.TypeToken +import com.ss.android.ugc.bytex.common.graph.ClassEntity +import com.ss.android.ugc.bytex.common.log.LevelLog +import java.io.* +import java.lang.reflect.Modifier + +/** + * Created by yangzhiqian on 2019-12-01
+ */ +class GsonClassesCache(private val delegate: ICache>? = null) : IClassCache { + companion object { + private val GSON by lazy { + GsonBuilder() + .excludeFieldsWithModifiers(Modifier.TRANSIENT) + .disableHtmlEscaping() + .registerTypeAdapterFactory(GraphTypeAdapterFactory()) + .create() + } + } + + override fun loadCache(t: File?): List? { + delegate?.loadCache(t)?.apply { return this } + if (t == null) { + return null + } + try { + if (!t.exists() || !t.isFile) { + return null + } + BufferedReader(FileReader(t)).use { reader -> + return GSON.fromJson>(reader, object : TypeToken>() { + }.type).apply { + println("Load ByteX Classes Cache Success[File]:" + t.absolutePath) + } + } + } catch (e: Exception) { + t.delete() + println("Load ByteX Classes Cache Fail[File]:" + t.absolutePath) + LevelLog.sDefaultLogger.e("loadCache failure", e) + } + return null + } + + override fun saveCache(t: File?, d: List): Boolean { + delegate?.saveCache(t, d) + if (t == null) { + return false + } + t.parentFile.mkdirs() + t.delete() + t.createNewFile() + BufferedWriter(FileWriter(t)).use { writer -> + GSON.toJson(d, writer) + writer.flush() + } + println("Save ByteX Classes Cache Succeed[File]:" + t.absolutePath) + return true + } +} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GsonGraphCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GsonGraphCache.kt deleted file mode 100644 index 8e9fc13..0000000 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/GsonGraphCache.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.ss.android.ugc.bytex.common.graph.cache - -import com.google.gson.GsonBuilder -import com.google.gson.reflect.TypeToken -import com.ss.android.ugc.bytex.common.graph.ClassEntity -import com.ss.android.ugc.bytex.common.graph.Graph -import com.ss.android.ugc.bytex.common.graph.GraphBuilder -import com.ss.android.ugc.bytex.common.graph.IGraphCache -import com.ss.android.ugc.bytex.common.log.LevelLog -import com.ss.android.ugc.bytex.transformer.concurrent.Schedulers -import java.io.* -import java.lang.reflect.Modifier -import java.util.stream.Collectors - -/** - * Created by yangzhiqian on 2019-12-01
- */ -object GsonGraphCache : IGraphCache { - private val GSON by lazy { - GsonBuilder() - .excludeFieldsWithModifiers(Modifier.TRANSIENT) - .disableHtmlEscaping() - .registerTypeAdapterFactory(GraphTypeAdapterFactory()) - .create() - } - private var ramCaches: RAMGraphCache? = null - var asyncSaveCache = true - - fun useRamCache(use: Boolean) { - ramCaches = if (use) { - RAMGraphCache - } else { - RAMGraphCache.clear() - null - } - } - - override fun loadCache(t: File?, graphBuilder: GraphBuilder): Boolean { - if (t == null) { - return false - } - try { - if (ramCaches?.loadCache(t, graphBuilder) == true) { - println("Load ByteX Cache Success:from RAM") - return true - } - if (!t.exists() || !t.isFile) { - return false - } - BufferedReader(FileReader(t)).use { reader -> - GSON.fromJson>(reader, object : TypeToken>() { - }.type).apply { - //经过抖音cache测试性能,结果多线程方案差不多,但大约结果是 - // Schedulers.COMPUTATION().submitAndAwait node.entity } - .collect(Collectors.toList()) - .let { list -> - t.parentFile.mkdirs() - t.delete() - t.createNewFile() - Schedulers.IO().submit { - BufferedWriter(FileWriter(t)).use { writer -> - GSON.toJson(list, writer) - writer.flush() - } - println("Save ByteX Cache Succeed:" + t.absolutePath) - } - }.apply { - if (!asyncSaveCache) { - get() - } - } - return true - } catch (e: Exception) { - t.delete() - e.printStackTrace() - LevelLog.sDefaultLogger.e("Save ByteX Cache failure", e) - } - return false - } -} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/ICache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/ICache.kt new file mode 100644 index 0000000..44e77a1 --- /dev/null +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/ICache.kt @@ -0,0 +1,11 @@ +package com.ss.android.ugc.bytex.common.graph.cache; + +/** + * Created by yangzhiqian on 2020-7-13
+ */ +interface ICache { + + fun loadCache(t: T?): D? + + fun saveCache(t: T?, d: D): Boolean +} diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/IClassCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/IClassCache.kt new file mode 100644 index 0000000..67d4461 --- /dev/null +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/IClassCache.kt @@ -0,0 +1,9 @@ +package com.ss.android.ugc.bytex.common.graph.cache + +import com.ss.android.ugc.bytex.common.graph.ClassEntity +import java.io.File + +/** + * Created by yangzhiqian on 2020/7/13
+ */ +interface IClassCache : ICache> \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/IGraphCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/IGraphCache.kt new file mode 100644 index 0000000..e5e13ae --- /dev/null +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/IGraphCache.kt @@ -0,0 +1,13 @@ +package com.ss.android.ugc.bytex.common.graph.cache + +import com.ss.android.ugc.bytex.common.graph.Graph +import java.util.concurrent.Future + +/** + * Created by yangzhiqian on 2020/7/13
+ */ + +interface IGraphCache { + fun loadCache(t: T?, graphBuilder: CachedGraphBuilder): Boolean + fun saveCache(t: T?, graph: Graph): Boolean +} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/RAMClassesCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/RAMClassesCache.kt new file mode 100644 index 0000000..01deb9f --- /dev/null +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/RAMClassesCache.kt @@ -0,0 +1,38 @@ +package com.ss.android.ugc.bytex.common.graph.cache + +import com.ss.android.ugc.bytex.common.graph.ClassEntity +import java.io.File +import java.util.concurrent.ConcurrentHashMap + +/** + * Created by yangzhiqian on 2020-03-04
+ */ +object RAMClassesCache : IClassCache { + private val caches = ConcurrentHashMap>() + + fun clear() { + caches.clear() + } + + fun clearCache(f: File) { + caches.remove(f.absolutePath) + } + + override fun loadCache(t: File?): List? { + if (t == null) { + return null + } + return caches.remove(t.absolutePath)?.apply { + println("Load ByteX Classes Cache Success[RAM]:" + t.absolutePath) + } + } + + override fun saveCache(t: File?, d: List): Boolean { + if (t == null) { + return false + } + println("Save ByteX Classes Cache Success[RAM]:" + t.absolutePath) + caches[t.absolutePath] = d + return true + } +} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/RAMGraphCache.kt b/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/RAMGraphCache.kt deleted file mode 100644 index 0cecd59..0000000 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/RAMGraphCache.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.ss.android.ugc.bytex.common.graph.cache - -import com.ss.android.ugc.bytex.common.graph.ClassEntity -import com.ss.android.ugc.bytex.common.graph.Graph -import com.ss.android.ugc.bytex.common.graph.GraphBuilder -import com.ss.android.ugc.bytex.common.graph.IGraphCache -import java.io.File -import java.util.stream.Collectors - -/** - * Created by yangzhiqian on 2020-03-04
- */ -object RAMGraphCache : IGraphCache { - private val caches = HashMap>() - - fun clear() { - caches.clear() - } - - fun clearCache(f: File) { - synchronized(caches) { - caches.remove(f.absolutePath) - } - } - - override fun loadCache(t: File?, graphBuilder: GraphBuilder): Boolean { - if (t == null) { - return false - } - synchronized(caches) { - caches.remove(t.absolutePath) ?: return false - }.apply { - //经过抖音cache测试性能,结果多线程方案差不多,但大约结果是 - // Schedulers.COMPUTATION().submitAndAwait node.entity }.collect(Collectors.toList())) - } - return true - } -} \ No newline at end of file diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileAnalyzer.java b/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileAnalyzer.java index 143c236..6b176ef 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileAnalyzer.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileAnalyzer.java @@ -67,6 +67,10 @@ public void handle(FileData fileData) { ClassReader cr = new ClassReader(raw); int flag = getFlag(handlers); ClassVisitorChain chain = getClassVisitorChain(relativePath); + if (this.mGraphBuilder != null) { + //do generate class diagram + chain.connect(new GenerateGraphClassVisitor(process == TRAVERSE_ANDROID, mGraphBuilder)); + } pluginList.forEach(plugin -> { switch (process) { case TRAVERSE_INCREMENTAL: @@ -82,10 +86,6 @@ public void handle(FileData fileData) { throw new RuntimeException("Unsupported Process"); } }); - if (this.mGraphBuilder != null) { - //do generate class diagram - chain.connect(new GenerateGraphClassVisitor(process == TRAVERSE_ANDROID, mGraphBuilder)); - } ClassNode cn = new SafeClassNode(); chain.append(cn); chain.accept(cr, flag); diff --git a/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileTransformer.java b/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileTransformer.java index 60c4778..6c9e28a 100644 --- a/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileTransformer.java +++ b/common/src/main/java/com/ss/android/ugc/bytex/common/processor/ClassFileTransformer.java @@ -64,15 +64,13 @@ public void handle(FileData fileData) { } } cn.accept(cw); - if (!GlobalWhiteListManager.INSTANCE.shouldIgnore(fileData.getRelativePath())) { - raw = cw.toByteArray(); - if (needVerify) { - ClassNode verifyNode = new ClassNode(); - new ClassReader(raw).accept(verifyNode, crFlags); - AsmVerifier.verify(verifyNode); - } - fileData.setBytes(raw); + raw = cw.toByteArray(); + if (needVerify) { + ClassNode verifyNode = new ClassNode(); + new ClassReader(raw).accept(verifyNode, crFlags); + AsmVerifier.verify(verifyNode); } + fileData.setBytes(raw); } catch (ByteXException e) { throw e; } catch (Exception e) { diff --git a/gradle/ext.gradle b/gradle/ext.gradle index 74c12c2..a58efdc 100644 --- a/gradle/ext.gradle +++ b/gradle/ext.gradle @@ -32,7 +32,7 @@ ext { upload_password_snapshot = PASSWORD_SNAPSHOT upload_maven_url_snapshot = UPLOAD_MAVEN_URL_SNAPSHOT upload_group = 'com.bytedance.android.byteX' - upload_version = "0.1.7${(useSnapshotMaven.toBoolean() ? "-${doSh("git config user.name")}-SNAPSHOT" : "")}" + upload_version = "0.1.8${(useSnapshotMaven.toBoolean() ? "-${doSh("git config user.name")}-SNAPSHOT" : "")}" upload_dir = project.rootProject.file('gradle_plugins').path gradle_version = '3.5.3' gson_version = '2.8.2' diff --git a/refer-check-plugin/src/main/java/com/ss/android/ugc/bytex/refercheck/ReferCheckContext.java b/refer-check-plugin/src/main/java/com/ss/android/ugc/bytex/refercheck/ReferCheckContext.java index 4295739..f90e6ae 100644 --- a/refer-check-plugin/src/main/java/com/ss/android/ugc/bytex/refercheck/ReferCheckContext.java +++ b/refer-check-plugin/src/main/java/com/ss/android/ugc/bytex/refercheck/ReferCheckContext.java @@ -182,11 +182,15 @@ public Map getNotFoundFields() { public void releaseContext() { super.releaseContext(); - methodCache.release(); - fieldCache.release(); + if (methodCache != null) { + methodCache.release(); + methodCache = null; + } + if (fieldCache != null) { + fieldCache.release(); + fieldCache = null; + } notAccessMethods.clear(); - methodCache = null; - fieldCache = null; } } diff --git a/settings.gradle b/settings.gradle index 8df8406..d14d456 100644 --- a/settings.gradle +++ b/settings.gradle @@ -20,6 +20,12 @@ include ':base-plugin' include ':common' include ':TransformEngine' include ':HookProguard' +include ':ProguardConfigurationResolver' +include ':ProguardConfigurationResolver-task' +include ':ProguardConfigurationResolver-transform' +project(':ProguardConfigurationResolver').projectDir = new File('HookProguard/ProguardConfigurationResolver') +project(':ProguardConfigurationResolver-task').projectDir = new File('HookProguard/ProguardConfigurationResolver/task') +project(':ProguardConfigurationResolver-transform').projectDir = new File('HookProguard/ProguardConfigurationResolver/transform') include ':GradleToolKit' include ':GradleEnvApi' project(':GradleEnvApi').projectDir = new File('GradleToolKit/GradleEnvApi')