【问题标题】:Crashlytics Generate Symbols gradle step fails: GC Overhead Limit ExceededCrashlytics Generate Symbols gradle 步骤失败:GC Overhead Limit Exceeded
【发布时间】:2019-12-28 15:09:12
【问题描述】:

我正在将项目从 gradle 版本 3.3 转换为 4.10.1。该项目主要是使用自定义构建步骤构建的 C++ 代码,而不是 CMake (externalNativeBuild) 或 Android.mk(ndkBuild)。它产生以下库:

armeabi-v7a unstripped: 883.2MB
arm64-v8a unstripped: 864.6MB
armeabi-v7a stripped: 15.6MB
arm64-v8a stripped: 23.9MB

构建过程在 crashlyticsGenerateSymbolsGoogleDistribution 步骤失败,并出现错误 OutOfMemoryError: GC Overhead Limit Exceeded。

是否有为 crashlytics 插件步骤提供更多内存的方法或参数?


顶级 gradle.properties 文件包含以下 jvm 参数: org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=512m - 尽管我已经尝试过和 org.gradle.jvmargs=-Xmx12g:MaxPermSize=2g 一样多的尝试。对这些值的更改似乎不会影响 crashlyticsGenerateSymbols 步骤。

如果我运行 assembleGoogleDistribution 构建,跳过 crashlytics 步骤,构建完成没有问题。

构建堆栈跟踪:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':application:crashlyticsGenerateSymbolsGoogleDistribution'.
> GC overhead limit exceeded

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':application:crashlyticsGenerateSymbolsGoogleDistribution'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:110)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77)
    at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
    at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
    at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
    at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
    at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
    at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
    at org.gradle.execution.taskgraph.LocalTaskInfoExecutor.execute(LocalTaskInfoExecutor.java:42)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:277)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:262)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.interleaveRanges(DwarfDataParser.java:321)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processChildDebugInfoEntries(DwarfDataParser.java:275)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.processCompilationUnit(DwarfDataParser.java:194)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.readCompilationUnit(DwarfDataParser.java:173)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.readCompilationUnit(DwarfDataParser.java:139)
    at com.crashlytics.tools.utils.dwarf.DwarfDataParser.parse(DwarfDataParser.java:62)
    at com.crashlytics.tools.utils.elf.ElfDataParser.parseElf(ElfDataParser.java:131)
    at com.crashlytics.tools.utils.elf.ElfDataParser.parse(ElfDataParser.java:101)
    at com.crashlytics.tools.utils.elf.ElfDataParser.parse(ElfDataParser.java:39)
    at com.crashlytics.tools.android.project.codemapping.csym.ElfCSymFactory.createCSymFromFile(ElfCSymFactory.java:99)
    at com.crashlytics.tools.android.project.codemapping.csym.NdkCSymGenerator.generateCodeMappings(NdkCSymGenerator.java:70)
    at com.crashlytics.tools.android.project.CSymManager.generate(CSymManager.java:96)
    at com.crashlytics.tools.android.DeveloperTools.processProperties(DeveloperTools.java:692)
    at com.crashlytics.tools.android.DeveloperTools.processArgsInternal(DeveloperTools.java:348)
    at com.crashlytics.tools.android.DeveloperTools.gradleMain(DeveloperTools.java:292)



Gradle 和 Java 信息​​:

./gradlew --version

------------------------------------------------------------
Gradle 4.10.1
------------------------------------------------------------

Build time:   2018-09-12 11:33:27 UTC
Revision:     76c9179ea9bddc32810f9125ad97c3315c544919

Kotlin DSL:   1.0-rc-6
Kotlin:       1.2.61
Groovy:       2.4.15
Ant:          Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM:          1.8.0_121 (Oracle Corporation 25.121-b13)
OS:           Mac OS X 10.13.6 x86_64

顶级 build.gradle

...
buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.0'
        classpath 'com.google.gms:google-services:4.1.0'
        classpath 'io.fabric.tools:gradle:1.31.0'
    }
}
...

应用程序构建.gradle

apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
...
crashlytics {
    enableNdk true
    androidNdkOut './../../../build/crashlytics'
    androidNdkLibsOut './../../../build/crashlytics/lib'
}
...
dependencies {
    // Crashlytics Kit
    implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
        transitive = true
    }
    // NDK Kit
    implementation('com.crashlytics.sdk.android:crashlytics-ndk:2.1.0@aar') {
        transitive = true
    }
}
...

(我已确认 androidNdkOut 路径包含 armeabi-v7a 和 arm64-v8a 文件夹,其中包含我们未剥离的 libnative.so 文件,而 androidNdkLibsOut 包含与我们剥离的 libnative.so 文件相同的文件夹)


我如何确保 crashlytics 插件为其 crashlyticsGenerateSymbols 步骤获得足够的内存,从而不超过垃圾收集器的开销?

【问题讨论】:

  • 尝试一些旧版本的 Fabric Gradle 插件是否可以摆脱 OOM?低至 1.28.0 可能值得尝试。 docs.fabric.io/android/changelog.html#fabric-gradle-plugin
  • 我尝试了包括 1.28.0 在内的所有版本,但均未成功。该项目是从 1.24.2 升级的(它工作的地方,但现在那个版本太旧了)
  • 谢谢,所以无论您在生成符号时使用的插件版本如何,看起来都会发生 OOM。您能否在未剥离的二进制文件上运行以下命令并查看输出有多大? readelf --debug-dump=info <path_to_.so> -> ~/sample/directory/dump.txt 文件大小大约是我们首先读取以生成符号的原始调试信息的大小。
  • 你能解决这个问题吗,因为我也遇到了同样的错误?
  • 我没有,问题是我们的原生符号最终每个架构约为 6.5GB,而 Crashlytics gradle 插件根本无法处理这个问题。该插件可能应该根据需要将符号输入/输出,而不是一次将它们加载到内存结构中。我不确定这有多容易,要修复多少工作。不幸的是,这在插件开发人员手中。

标签: crashlytics google-fabric


【解决方案1】:

尝试将文件fabric.properties放到app目录下,内容如下

disableEnhancedSymbolGeneration=true

它禁用 DWARF 信息处理,但在映射中保留符号信息。 在这种情况下,您不会在结果堆栈跟踪中获得文件名和行。你仍然会得到完整的函数名(包括命名空间)而不是函数地址。

【讨论】:

  • 有谁知道 Firebase Crashlytics 的诀窍——这显然有同样的问题?
  • 这不会对 Crashlytics 插件的内存使用产生有意义的影响 - 我们总共有 13GB 的符号扩展到内存中,然后用于生成输出(也在内存中)。问题在于架构。符号应该以块的形式流入和处理,而不是全部加载到内存中以供工厂从头到尾处理。
【解决方案2】:

请尝试在 build.gradle 中将 Fabric 插件从 1.31.0 降级为 1.25.4

classpath 'io.fabric.tools:gradle:1.25.4'

【讨论】:

  • 与较新的库和工具不兼容,因此项目首先要升级。
  • 我的项目中仍然使用fabric 1.25.4,一切都还好。我之前也遇到过同样的问题,所以我建议降级它。使用1.25.4时是否出现日志错误
  • 我不记得我必须进行的所有更改,以及我在此过程中看到的错误消息。现在已经9个多月了。您在项目中使用 Android X 库吗?您使用什么版本的 Gradle 和 Android 插件?
  • 我使用 Android X,Gradle 4.6,这里是依赖关系 classpath 'com.android.tools.build:gradle:3.2.1' classpath 'io.fabric.tools:gradle:1.25.4` classpath 'com.google.gms:google-services:4.1.0 我的 SO 大小和你的相似,armeabi- v7a:750MB,arm64-v8a:780MB
【解决方案3】:

我遇到了这个问题,发现有两个走来走去。 1:使用NDK r18和Android Gradle插件3.4.2。 (19 及更高版本的 NDK 在为 arm64-v8a 生成符号时会导致 java 堆问题) 2:使用最新的 NDK r21d 并设置链接器标志 -fuse-ld=lld 如果使用 ndkBuild,在 application.mk 中设置 APP_LDFLAGS += -fuse-ld=lld

这两个人帮助我解决了这个问题。

【讨论】:

    猜你喜欢
    • 2018-06-03
    • 2016-08-31
    • 2012-06-09
    • 2015-11-30
    • 1970-01-01
    • 2015-05-04
    • 2020-10-04
    • 1970-01-01
    • 2015-02-06
    相关资源
    最近更新 更多