Ich habe ein Java+Kotlin-Connector-Projekt für eine native Bibliothek (nennen wir sie libfoo.so) mit JNA erstellt, für das etwa 100 Komponententests geschrieben wurden dafür und wollte sehen, ob in diesen Tests irgendwelche Lecks in libfoo auftreten. Was ich jetzt getan habe, um nach ihnen zu suchen:
- Verwenden Sie einen Ubuntu 24.04-Docker mit Clang 17, um dieses Problem zu vermeiden; Mein Hostsystem ist ein aktuelles Arch Linux.
- kompiliere libfoo mit Adressbereinigung und lege es auf einen Pfad, wo JNA es findet
Code: Select all
export LD_PRELOAD="/usr/lib/llvm-17/lib/clang/17/lib/linux/libclang_rt.asan-x86_64.so"
- um dieses Problem zu vermeiden
Code: Select all
export ASAN_OPTIONS="handle_segv=0"
- erstellen Sie eine Datei lsan.supp mit dem Inhalt „leak:libjvm\nleak:libjli\nleak:libz\nleak:liblcms\nleak: liblcms2\nleak:libawt\n" und fügen Sie es zu LSAN_OPTIONS envvar hinzu, da Java viele falsch positive „Lecks“ verursacht und Ich interessiere mich nicht für diese, nur für libfoo
- run gradlew build, um das Projekt neu zu erstellen und zu testen; gradlew sollte ein automatisch generiertes Standardskript sein (ich bin kein Java-Typ und nicht der Autor dieses Projekts), relevanter Inhalt von build.gradle unten – beachten Sie, dass es auf Java Version 11 abzielt
Code: Select all
plugins {
id 'distribution'
id 'jacoco'
id 'net.researchgate.release' version '2.8.1'
id 'org.jetbrains.kotlin.jvm' version '1.7.21'
}
ext {
assertjVersion = '3.23.1'
annotationsVersion = '23.0.0'
commonsLang3Version = '3.12.0'
jUnitVersion = '5.8.2'
}
allprojects {
repositories {
mavenCentral()
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'kotlin'
group 'foo'
version "$version"
compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"
java {
withSourcesJar()
}
kotlin {
jvmToolchain(11)
}
compileKotlin {
kotlinOptions.jvmTarget = JavaVersion.VERSION_11
}
compileTestKotlin {
kotlinOptions.jvmTarget = JavaVersion.VERSION_11
}
}
Code: Select all
Direct leak of 4 byte(s) in 4 object(s) allocated from:
#0 0x7e475ecfb372 in malloc (/usr/lib/llvm-17/lib/clang/17/lib/linux/libclang_rt.asan-x86_64.so+0xfb372) (BuildId: 91f375f2a48c6b133a56d8cc059d017ae5de4982)
#1 0x7e4746abaa13 ()
#2 0x7e473fa103f3 ()
#3 0x7e473ee09fdf ()
#4 0x7e473f79ff33 ()
Ich vermute, dass wann Die Ausführung dauert lange genug oder ist komplex genug, etwas Java? Bibliotheken werden zum Zeitpunkt der Leckanalyse entladen. Ich glaube nicht, dass es sich um ein tatsächliches Leck handelt, da es nicht immer auftritt, und auch nicht, dass es ein Problem mit libfoo selbst ist, da es seit einigen Jahren gerne in der Produktion verwendet wird.
Dinge, die ich in Betracht gezogen/ausprobiert habe:
- Ich dachte, dass die fraglichen entladenen Bibliotheken mit dem Laden von Bildern (Teilen von Texteinbauten) zu tun haben javax.imageio.ImageIO, da es ein ähnlich unregelmäßiges Leck gab, bei dem liblcms oder liblcms2 manchmal auftraten, aber das Vorladen dieser Bibliotheken half nicht.
< li>Das Festlegen von LD_DEBUG envvar erzeugt Tausende von Ausgabezeilen, auch wenn es nur LD_DEBUG=libs ist, aber ich kann darin nichts Nützliches finden. - Die Verwendung nur eines Tests mit langer Wartezeit hilft nicht, das Problem muss spezifischer bei den hier verwendeten Tests liegen.
- Leider kann ich den nativen Test nicht posten lib oder sogar die vollständigen Unit-Tests, da alles proprietär ist. Vielleicht werde ich es irgendwann auf etwas hinreichend Anonymes vereinfachen, aber es ist eine Menge Arbeit aufgrund der schieren Anzahl an Tests und des Herumbastelns daran, um sicherzustellen, dass das Leck normalerweise auftritt.
- Ich habe gesucht Möglichkeiten zur Unterdrückung unbekannter Modullecks, es wurde jedoch keine LSA-Einstellung dafür gefunden.
- Es ist nicht spezifisch für nur eine Version des Compilers für native Bibliothek, Sanitizer, Build-System, Host-System, Gradle Version oder Ziel-Java-Version (derzeit 11). Es ist seit mindestens 2 Jahren vorhanden und alle diese Dinge wurden aktualisiert, aber der Fehler bleibt bestehen.
Ich kann immer auf „Rückgabe verwerfen“ zurückgreifen Wert, lassen Sie jemanden manuell prüfen, ob ein Leck in libfoo vorliegt wird gemeldet“-Ansatz, aber ich würde ihn gerne sauber automatisieren, indem ich dafür sorge, dass diese Lecks nicht gemeldet werden.