36
import java.lang.management.ManagementFactory;
37
import java.lang.management.MemoryMXBean;
38
import java.time.Duration;
39
import java.time.Instant;
40
import java.util.ArrayList;
41
import java.util.Collections;
42
import java.util.LinkedList;
43
import java.util.concurrent.ConcurrentLinkedQueue;
44
import java.util.concurrent.CountDownLatch;
45
import java.util.concurrent.ExecutorService;
46
import java.util.concurrent.Executors;
47
import java.util.concurrent.TimeUnit;
48
import com.sun.management.ThreadMXBean;
50
import jdk.test.lib.Asserts;
51
import jdk.test.lib.process.ProcessTools;
52
import jdk.test.lib.process.OutputAnalyzer;
54
public class TestStressG1Uncommit {
55
public static void main(String[] args) throws Exception {
56
ArrayList<String> options = new ArrayList<>();
57
Collections.addAll(options,
58
"-Xlog:gc,gc+heap+region=debug",
60
StressUncommit.class.getName()
62
OutputAnalyzer output = ProcessTools.executeLimitedTestJava(options);
63
output.shouldHaveExitValue(0);
64
output.shouldMatch("Uncommit regions");
65
output.outputTo(System.out);
70
private static final long M = 1024 * 1024;
71
private static final long G = 1024 * M;
72
private static final Instant StartTime = Instant.now();
74
private static final ThreadMXBean threadBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
75
private static final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
76
private static ConcurrentLinkedQueue<Object> globalKeepAlive;
78
public static void main(String args[]) throws InterruptedException {
80
long allocationSize = (long) (Runtime.getRuntime().maxMemory() * 0.8);
83
int gigsOfAllocation = (int) Math.ceil((double) allocationSize / G);
84
int numWorkers = Math.min(gigsOfAllocation, Runtime.getRuntime().availableProcessors());
85
long workerAllocation = allocationSize / numWorkers;
87
log("Using " + numWorkers + " workers, each allocating: ~" + (workerAllocation / M) + "M");
88
ExecutorService workers = Executors.newFixedThreadPool(numWorkers);
92
while (uptime() < 60) {
93
log("Interation: " + iteration++);
94
globalKeepAlive = new ConcurrentLinkedQueue<>();
96
CountDownLatch workersRunning = new CountDownLatch(numWorkers);
97
for (int j = 0; j < numWorkers; j++) {
99
workers.submit(() -> {
100
allocateToLimit(workerAllocation);
101
workersRunning.countDown();
106
workersRunning.await();
109
globalKeepAlive = null;
112
long committedBefore = memoryBean.getHeapMemoryUsage().getCommitted();
114
long committedAfter = memoryBean.getHeapMemoryUsage().getCommitted();
115
Asserts.assertLessThan(committedAfter, committedBefore);
119
workers.awaitTermination(5, TimeUnit.SECONDS);
123
private static void allocateToLimit(long limit) {
124
var localKeepAlive = new LinkedList<byte[]>();
126
long currentAllocation = threadBean.getCurrentThreadAllocatedBytes();
127
long allocationLimit = currentAllocation + limit;
129
while (currentAllocation < allocationLimit) {
131
for (long j = 0 ; j < 1000; j++) {
132
localKeepAlive.add(new byte[1024]);
134
currentAllocation = threadBean.getCurrentThreadAllocatedBytes();
138
globalKeepAlive.add(localKeepAlive);
141
private static long uptime() {
142
return Duration.between(StartTime, Instant.now()).getSeconds();
145
private static void log(String text) {
146
System.out.println(uptime() + "s: " + text);