9
votes

Échec de l'étape de gradation Crashlytics Generate Symbols: Limite de frais généraux du GC dépassée

Je convertis un projet de la version gradle 3.3 vers la version 4.10.1. Ce projet est principalement du code C ++ construit à l'aide d'une étape de construction personnalisée - pas CMake (externalNativeBuild) ou Android.mk (ndkBuild). Il produit les bibliothèques suivantes:

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
    }
}
...

Le processus de génération échoue à l'étape crashlyticsGenerateSymbolsGoogleDistribution, avec l'erreur OutOfMemoryError: GC Overhead Limit Exceeded.

Existe-t-il une méthode ou un argument pour fournir plus de mémoire à l'étape du plugin crashlytics?


Le fichier gradle.properties de niveau supérieur contient les arguments jvm suivants: org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=512m - bien que j'aie essayé autant que org.gradle.jvmargs=-Xmx12g:MaxPermSize=2g . Aucune modification de ces valeurs ne semble affecter l'étape crashlyticsGenerateSymbols.

Si j'exécute une compilation assembleGoogleDistribution, en ignorant l'étape crashlytics, la compilation se termine sans problème.

Créer une trace de pile:

...
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'
    }
}
...

Informations sur Gradle et 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 de niveau supérieur

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)


application build.gradle

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

(J'ai confirmé que le chemin androidNdkOut contient les dossiers armeabi-v7a et arm64-v8a qui contiennent nos fichiers libnative.so non rayés, et androidNdkLibsOut contient les mêmes dossiers avec nos fichiers libnative.so supprimés)


Comment puis-je m'assurer que le plugin crashlytics dispose de suffisamment de mémoire pour son étape crashlyticsGenerateSymbols afin qu'il ne dépasse pas la surcharge du ramasse-miettes?


6 commentaires

L'essai de quelques anciennes versions du plugin Fabric Gradle permet-il de se débarrasser du MOO? Cela pourrait valoir la peine d'essayer jusqu'à 1.28.0. docs.fabric.io/android/changelog.html#fabric-gradle-plugin


J'ai essayé toutes les versions jusqu'à la 1.28.0 incluse sans succès. Le projet a été mis à jour à partir de la version 1.24.2 (où cela fonctionnait, mais cette version est maintenant trop ancienne)


Merci, on dirait donc qu'un MOO se produit quelle que soit la version du plugin que vous utilisez lorsque vous générez des symboles. Pourriez-vous exécuter la commande suivante sur votre binaire non rayé et voir la taille de la sortie? readelf --debug-dump=info <path_to_.so> -> ~/sample/directory/dump.txt la taille du fichier sera approximativement la taille des informations de débogage brutes que nous lisons pour générer des symboles en premier lieu.


Avez-vous pu résoudre ce problème car j'obtiens également la même erreur?


Je ne l'ai pas fait, le problème est que nos symboles natifs finissent par être d'environ 6,5 Go par architecture, et le plugin Crashlytics gradle ne gère pas du tout cela. Le plugin devrait probablement diffuser les symboles en entrée / sortie selon les besoins, plutôt que de les charger dans une structure en mémoire en une seule fois. À quel point c'est facile à faire et combien de travail cela représente-t-il à réparer, je ne suis pas sûr. C'est malheureusement entre les mains des développeurs de plugins.


Rencontré le même problème, création du problème github.com/fabric/fabric/issues/2057


3 Réponses :


0
votes

Essayez de mettre un fichier fabric.properties dans le répertoire de l'application avec le contenu suivant

disableEnhancedSymbolGeneration=true

Il désactive le traitement des informations DWARF mais conserve les informations des symboles dans le mappage. Vous n'obtiendrez pas les noms de fichiers et les lignes dans les stacktraces résultantes dans ce cas. Néanmoins, vous obtiendrez des noms de fonction complets (y compris les espaces de noms) au lieu des adresses de fonction.


2 commentaires

Quelqu'un a trouvé l'astuce ici pour Firebase Crashlytics - qui a clairement le même problème?


Cela n'affectera pas de manière significative l'utilisation de la mémoire du plugin Crashlytics - nous avons une somme totale de 13 Go de symboles développés en mémoire, puis utilisés pour produire une sortie (également en mémoire). Le problème est architectural. Les symboles doivent être diffusés et traités par blocs, pas tous chargés en mémoire pour qu'une usine puisse les traiter du début à la fin.



0
votes

Veuillez essayer de rétrograder le Fabric Plugin de 1.31.0 à 1.25.4 dans build.gradle

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


4 commentaires

Non compatible avec les bibliothèques et outils plus récents, d'où la raison pour laquelle le projet a été mis à niveau en premier lieu.


J'utilise toujours le fabric 1.25.4 dans mon projet et tout va bien. J'ai eu le même problème avant, c'est pourquoi je suggère de le déclasser. Avez-vous l'erreur de journal lorsque vous utilisez 1.25.4


Je ne me souviens pas de tous les changements que j'ai dû faire et des messages d'erreur que j'ai vus en cours de route. C'était il y a plus de 9 mois maintenant. Utilisez-vous les bibliothèques Android X dans votre projet? Quelle version de Gradle et du plugin Android utilisez-vous?


J'utilise Android X, Gradle 4.6, voici le chemin de classe des dépendances 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 Ma taille SO est similaire à la vôtre, armeabi-v7a: 750 Mo, arm64-v8a: 780 Mo



0
votes

Je suis tombé sur ce problème et en ai trouvé deux à pied. 1: utilisez NDK r18 et le plugin Android Gradle 3.4.2. (NDK 19 et plus tard causera un problème de tas Java lors de la génération du symbole pour arm64-v8a) 2: utilisez le NDK le plus récent r21d et définissez le drapeau de l'éditeur de liens -fuse-ld = lld Si vous utilisez ndkBuild, définissez APP_LDFLAGS + = -fuse-ld = lld dans application.mk

Ces deux-là ont travaillé pour moi pour réussir ce problème.


0 commentaires