Speicherverlust in unbekanntem Modul mit JNA und JUnit gemeldetJava

Java-Forum
Anonymous
 Speicherverlust in unbekanntem Modul mit JNA und JUnit gemeldet

Post by Anonymous »

Dies ist ein spezifisches Problem, das ich beim Erstellen der MRE für meine frühere Frage festgestellt habe. Es ist nicht klar, ob es sich um dasselbe Problem handelt, auch wenn es verwandt zu sein scheint. Deshalb stelle ich es als separate Frage.
Betrachten Sie die folgende JUnit-Testklasse:

Code: Select all

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import java.lang.Integer;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;

public class MyTest {
private void dummyTest() {
new Memory(1024 * 9);
}

@Test
public void find() {
List list = new ArrayList();
list.add(new Integer(1));

list.stream().map(arg -> {
Pointer ptr = new Memory(1024 * 1024);
return ptr;
}).toArray(Pointer[]::new);
}

@Test
public void test001() {
dummyTest();
}

// [91 more identical tests named test002...test092 follow]
Ich führe es auf Docker Ubuntu 24.04 mit den Paketen openjdk-8-jdk clang-17 aus unter Verwendung von Gradle, mit vorinstalliertem Adressbereinigungsprogramm. JNA 5.12.1, JUnit 5.8.2, Hostsystem ist ein aktuelles Arch Linux. Skript zum Ausführen:

Code: Select all

echo -e "leak:libjvm\nleak:libjli\nleak:libz\nleak:liblcms\nleak:liblcms2\nleak:libjavalcms\nleak:libawt\n" >> lsan.supp
export LD_PRELOAD="/usr/lib/llvm-17/lib/clang/17/lib/linux/libclang_rt.asan-x86_64.so"
export ASAN_OPTIONS="handle_segv=0"
export LSAN_OPTIONS="suppressions="$(pwd)"/lsan.supp:print_suppressions=0"

./gradlew clean test
Es wird regelmäßig der folgende Leckbericht erstellt:

Code: Select all

Direct leak of 1048576 byte(s) in 1 object(s) allocated from:
#0 0x759245cfb372 in malloc (/usr/lib/llvm-17/lib/clang/17/lib/linux/libclang_rt.asan-x86_64.so+0xfb372) (BuildId: 91f375f2a48c6b133a56d8cc059d017ae5de4982)
#1 0x7592316185e6  ()
#2 0x759231607bcf  ()
#3 0x759231607bcf  ()
#4 0x7592316080f5  ()
#5 0x759231607e3f  ()
#6 0x75923197befb  ()

SUMMARY: AddressSanitizer: 1048576 byte(s) leaked in 1 allocation(s).
Dies bezieht sich eindeutig auf den in Zeile 19 zugewiesenen nativen Speicher. Da eine Instanz von Memory den nativen Speicher auf gc freigeben sollte, glaube ich nicht, dass es sich um ein echtes Leck handelt – Vielmehr sieht es so aus, als würde JNA entladen, bevor das passiert. Allerdings:
  • ArrayList, stream und toArray entfernen und Pointer[] ptrs = new direkt erstellen Zeiger[1]; ptrs[0] = new Memory(1024 * 1024); lässt den Leckbericht verschwinden
  • Durch die Reduzierung der Anzahl der Dummy-Tests verschwindet der Leckbericht, abhängig von der genauen Anzahl
  • Das Ändern der Namen der Tests kann dazu führen, dass der Leckbericht ebenfalls verschwindet
Der mallocierte native Speicher wird in meinem Code nie berührt, daher denke ich darüber nach die Möglichkeit eines seltsamen Verhaltens im Zusammenhang mit einer Speicherüberbelegung.
Es könnte auch mit der von JUnit festgelegten Reihenfolge der Tests zusammenhängen. Das ist die einzige Erklärung, die mir einfällt, warum Namen von Tests wichtig sind.
Ich habe ein vollständiges Repo erstellt, um diesen Fehler bequem zu reproduzieren, indem ich run.sh aufrufe. Alle relevanten Informationen und der Code werden in diese Frage kopiert.
Meine Frage hier ist: Was genau verursacht diesen speziellen Leckbericht?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post