-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
11, 17, 19, 20, 21
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
when i use object.wait() in jdk17, i meet a memory increase problem. If i add the VM options -XX:GuaranteedSafepointInterval=0, using native memory tracking can found that the JVM_MonitorWait malloc (which belong to internal type memory) is keep increasing.
when i remove the -XX:GuaranteedSafepointInterval=0 setting, the JVM_MonitorWait malloc can be recycled after increasing to little MB
when i run in jdk8, i can not trace the JVM_MonitorWait malloc.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
step1: run source code main class in jkd17 with VM options: -XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=0
step2: execute this command to set a baseline
jcmd <pid> VM.native_memory baseline
step3: execute this command to see diff
while true; do jcmd <pid> VM.native_memory detail.diff | grep -A 3 "JVM_Monitor"; sleep 1; done
ACTUAL -
the malloc keep increasing.
[0x0000000105914b3c] JVM_MonitorWait+0x1b0
[0x000000010e52a634]
(malloc=32528KB type=Internal +32528KB #160138 +160138)
[0x0000000105914b3c] JVM_MonitorWait+0x1b0
[0x000000010e52a634]
(malloc=32946KB type=Internal +32946KB #162196 +162196)
[0x0000000105914b3c] JVM_MonitorWait+0x1b0
[0x000000010e52a634]
(malloc=33750KB type=Internal +33750KB #166152 +166152)
---------- BEGIN SOURCE ----------
class DemoFuture {
private final Object lock = new Object();
private volatile boolean completed;
private volatile String result;
public boolean completed(String res) {
synchronized (lock) {
if (this.completed) {
return false;
}
this.completed = true;
this.result = res;
lock.notifyAll();
}
return true;
}
public String get() throws InterruptedException {
synchronized (lock) {
while (!this.completed) {
lock.wait();
}
return getResult();
}
}
private String getResult() {
return this.result;
}
}
public class DemoFutureMain {
public static void main(String[] args) throws InterruptedException {
DemoFutureMain main = new DemoFutureMain();
while(true) {
main.test();
}
}
private void test() throws InterruptedException {
DemoFuture demoFuture = new DemoFuture();
Thread t = asyncDealResult(demoFuture);
String res = demoFuture.get();
System.out.println("res: " + res);
if (!t.isInterrupted()) {
System.out.println("thread interrupt");
t.interrupt();
}
}
private Thread asyncDealResult(DemoFuture demoFuture) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
demoFuture.completed("abc" + Math.random());
}
};
Thread t = new Thread(runnable);
t.start();
return t;
}
}
---------- END SOURCE ----------
when i use object.wait() in jdk17, i meet a memory increase problem. If i add the VM options -XX:GuaranteedSafepointInterval=0, using native memory tracking can found that the JVM_MonitorWait malloc (which belong to internal type memory) is keep increasing.
when i remove the -XX:GuaranteedSafepointInterval=0 setting, the JVM_MonitorWait malloc can be recycled after increasing to little MB
when i run in jdk8, i can not trace the JVM_MonitorWait malloc.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
step1: run source code main class in jkd17 with VM options: -XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=0
step2: execute this command to set a baseline
jcmd <pid> VM.native_memory baseline
step3: execute this command to see diff
while true; do jcmd <pid> VM.native_memory detail.diff | grep -A 3 "JVM_Monitor"; sleep 1; done
ACTUAL -
the malloc keep increasing.
[0x0000000105914b3c] JVM_MonitorWait+0x1b0
[0x000000010e52a634]
(malloc=32528KB type=Internal +32528KB #160138 +160138)
[0x0000000105914b3c] JVM_MonitorWait+0x1b0
[0x000000010e52a634]
(malloc=32946KB type=Internal +32946KB #162196 +162196)
[0x0000000105914b3c] JVM_MonitorWait+0x1b0
[0x000000010e52a634]
(malloc=33750KB type=Internal +33750KB #166152 +166152)
---------- BEGIN SOURCE ----------
class DemoFuture {
private final Object lock = new Object();
private volatile boolean completed;
private volatile String result;
public boolean completed(String res) {
synchronized (lock) {
if (this.completed) {
return false;
}
this.completed = true;
this.result = res;
lock.notifyAll();
}
return true;
}
public String get() throws InterruptedException {
synchronized (lock) {
while (!this.completed) {
lock.wait();
}
return getResult();
}
}
private String getResult() {
return this.result;
}
}
public class DemoFutureMain {
public static void main(String[] args) throws InterruptedException {
DemoFutureMain main = new DemoFutureMain();
while(true) {
main.test();
}
}
private void test() throws InterruptedException {
DemoFuture demoFuture = new DemoFuture();
Thread t = asyncDealResult(demoFuture);
String res = demoFuture.get();
System.out.println("res: " + res);
if (!t.isInterrupted()) {
System.out.println("thread interrupt");
t.interrupt();
}
}
private Thread asyncDealResult(DemoFuture demoFuture) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
demoFuture.completed("abc" + Math.random());
}
};
Thread t = new Thread(runnable);
t.start();
return t;
}
}
---------- END SOURCE ----------