Skip to content

Instantly share code, notes, and snippets.

@kelunik
Last active October 30, 2024 10:35
Show Gist options
  • Save kelunik/be51e5e2fdf746bbc86383b922bbb05e to your computer and use it in GitHub Desktop.
Save kelunik/be51e5e2fdf746bbc86383b922bbb05e to your computer and use it in GitHub Desktop.
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggingGCRaceConditionTester {
private static final Logger _log = LoggerFactory.getLogger(LoggingGCRaceConditionTester.class);
/**
* Start with -Xmx2G
*/
public static void main( String[] args ) {
new LoggingGCRaceConditionTester().test();
}
private static void joinQuietly( Thread t ) {
try {
t.join();
}
catch ( InterruptedException e ) {
throw new RuntimeException(e);
}
}
private static void setDaemon( Thread t ) {t.setDaemon(true);}
private volatile boolean endlessLoop = true;
void test() {
List<Thread> threads = List.of( //
new Thread(this::log, "Logger loop"), //
new Thread(this::gc, "GC loop") //
);
threads.forEach(LoggingGCRaceConditionTester::setDaemon);
threads.forEach(Thread::start);
threads.forEach(LoggingGCRaceConditionTester::joinQuietly);
}
private void gc() {
try {
Thread.sleep(10); // give the log thread a headstart
}
catch ( InterruptedException e ) {
throw new RuntimeException(e);
}
while ( true ) {
Thread.yield();
System.gc();
}
}
private void log() {
long suffix = 0;
boolean npe = false;
while ( true ) {
try {
String name = "TestLogger" + (++suffix);
try {
Logger l = LoggerFactory.getLogger(name);
if ( npe || (suffix % 100) == 0 ) {
l.info("");
} else {
l.trace("");
}
}
catch ( NullPointerException t ) {
_log.warn("{} threw {}: {}", name, t.getClass().getSimpleName(), t.getMessage());
npe = true;
}
catch ( Throwable t ) {
_log.error("{} threw {}: {}", name, t.getClass().getSimpleName(), t.getMessage());
}
}
catch ( Throwable t ) {
_log.error("caught", t);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment