diff --git a/java/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestNettyAllocator.java b/java/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestNettyAllocator.java index b9525d0fe9d31..07fdc3f784e43 100644 --- a/java/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestNettyAllocator.java +++ b/java/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestNettyAllocator.java @@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue; +import java.util.Collections; import java.util.stream.Collectors; import org.apache.arrow.memory.ArrowBuf; @@ -40,6 +41,7 @@ public class TestNettyAllocator { @Test public void testMemoryUsage() { ListAppender memoryLogsAppender = new ListAppender<>(); + memoryLogsAppender.list = Collections.synchronizedList(memoryLogsAppender.list); Logger logger = (Logger) LoggerFactory.getLogger("arrow.allocator"); try { logger.setLevel(Level.TRACE); @@ -52,13 +54,17 @@ public void testMemoryUsage() { boolean result = false; long startTime = System.currentTimeMillis(); while ((System.currentTimeMillis() - startTime) < 10000) { // 10 seconds maximum for time to read logs - result = memoryLogsAppender.list.stream() - .anyMatch( - log -> log.toString().contains("Memory Usage: \n") && - log.toString().contains("Large buffers outstanding: ") && - log.toString().contains("Normal buffers outstanding: ") && - log.getLevel().equals(Level.TRACE) - ); + // Lock on the list backing the appender since a background thread might try to add more logs + // while stream() is iterating over list elements. This would throw a flakey ConcurrentModificationException. + synchronized (memoryLogsAppender.list) { + result = memoryLogsAppender.list.stream() + .anyMatch( + log -> log.toString().contains("Memory Usage: \n") && + log.toString().contains("Large buffers outstanding: ") && + log.toString().contains("Normal buffers outstanding: ") && + log.getLevel().equals(Level.TRACE) + ); + } if (result) { break; }