回复: Dead Continuation cause resource leak?

Hui Shi kalinshi at qq.com
Thu May 28 11:06:59 UTC 2020


Hang Java thread will not be collected by GC. They can be iterated\located and try to interrupt and terminate it  - if possible, they still have chance to unwind stack and release resource. Ccorrect me if wrong.
Can the hang/blocked virtual threads be iterated and visited, before they are collected by GC? 


Agree, this might be application bugs, but difficult to locate for developers if continuation/vritual thread get collected.


Regards
Hui


------------------ 原始邮件 ------------------
发件人: "Ron Pressler"<ron.pressler at oracle.com>;
发送时间: 2020年5月28日(星期四) 晚上6:08
收件人: "loom-dev"<loom-dev at openjdk.java.net>;"Hui Shi"<kalinshi at qq.com>;

主题: Re: Dead Continuation cause resource leak?



 A continuation, or a virtual thread for that matter, that becomes unreachable before termination
corresponds to an ordinary platform thread that sleeps forever. Neither the JDK nor the OS makes
liveness guarantees about code.


Having said that, a virtual thread can become unreachable before termination only due to a serious
bug. When it is mounted, a reference to it is held by the scheduler or else it would be able to schedule
it, and when blocked (and unmounted) a reference to it is held by the blocking construct, or else
it would never be able to unblock it.


— Ron
 
 
 

On 28 May 2020 at 07:43:09, 施慧 (kalinshi at qq.com) wrote:
 
Hi All, 
 
 
Trying to understand Loom continuation implementation. In following LeakTest,&nbsp; Continuation Object is unreachable after first yield, but its runnable target is not finished yet. 
There might be some resources allcoated during continuation run (native memory in this test case and free in finally block --- not cleaner way), when continuation object is collected, these resources are not closed or freed. 
 
 
Is it possible to "clean up" a dead continuation which is not finished yet but collecting by GC?&nbsp; 
 
 
Tested with code cloned from github today. 
javac --add-exports java.base/jdk.internal.ref=ALL-UNNAMED --add-exports java.base/jdk.internal.misc=ALL-UNNAMED&nbsp; LeakTest.java 
java --add-exports java.base/jdk.internal.ref=ALL-UNNAMED --add-exports java.base/jdk.internal.misc=ALL-UNNAMED&nbsp; LeakTest 
clean continuation 
 
 
 
import jdk.internal.ref.Cleaner; 
import jdk.internal.misc.Unsafe; 
public class LeakTest { 
&nbsp; &nbsp; private static final Unsafe unsafe = Unsafe.getUnsafe(); 
&nbsp; &nbsp; static ContinuationScope scope = new ContinuationScope("scope"); 
&nbsp; &nbsp; public static void main(String[] args) throws Exception { 
&nbsp; &nbsp; &nbsp; &nbsp; bar(); 
&nbsp; &nbsp; &nbsp; &nbsp; System.gc(); 
&nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep(1000); 
&nbsp; &nbsp; &nbsp; &nbsp; System.gc(); 
&nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep(1000); 
&nbsp; &nbsp; } 
 
 
&nbsp; &nbsp; public static void bar() { 
&nbsp; &nbsp; &nbsp; &nbsp; Continuation cont = new Continuation(scope, () -&gt; { 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long mem = 0; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try { 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // open file/socket 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mem = unsafe.allocateMemory(100); 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Continuation.yield(scope); 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } finally { 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unsafe.freeMemory(mem); 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("release memory"); 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } 
&nbsp; &nbsp; &nbsp; &nbsp; }); 
&nbsp; &nbsp; &nbsp; &nbsp; Cleaner.create(cont, () -&gt; { System.out.println("clean continuation");&nbsp; }); 
&nbsp; &nbsp; &nbsp; &nbsp; cont.run(); 
&nbsp; &nbsp; &nbsp; &nbsp; //cont.run(); 
&nbsp; &nbsp; } 
} 
 
 
 
Regards


More information about the loom-dev mailing list