diff --git a/src/share/classes/java/lang/System.java b/src/share/classes/java/lang/System.java index 551a29c0649a611996f71071a9d698d9fae0740d..898629b7b43e2669bf75292e62d69f02da5feb82 100644 --- a/src/share/classes/java/lang/System.java +++ b/src/share/classes/java/lang/System.java @@ -1315,6 +1315,11 @@ public final class System { public AbstractResourceContainer getResourceContainer(Thread thread) { return thread.resourceContainer; } + + @Override + public AbstractResourceContainer getInheritedResourceContainer(Thread thread) { + return thread.inheritedResourceContainer; + } }); } } diff --git a/src/share/classes/java/lang/Thread.java b/src/share/classes/java/lang/Thread.java index e67486e9f898041fce600032d7951320bf666e47..1592d50e9c4eb957ec44b9094771df049e6c3a60 100644 --- a/src/share/classes/java/lang/Thread.java +++ b/src/share/classes/java/lang/Thread.java @@ -227,6 +227,11 @@ class Thread implements Runnable { */ AbstractResourceContainer resourceContainer; + /** + * {@code ResourceContainer} inherited from parent + */ + AbstractResourceContainer inheritedResourceContainer; + private static synchronized long nextThreadID() { return ++threadSeqNumber; } @@ -439,6 +444,7 @@ class Thread implements Runnable { /* com.alibaba.rcm API */ this.resourceContainer = AbstractResourceContainer.root(); + this.inheritedResourceContainer = parent.resourceContainer; /* Set the tenant container */ if (VM.isBooted() && TenantGlobals.isTenantEnabled()) { @@ -788,6 +794,8 @@ class Thread implements Runnable { blocker = null; uncaughtExceptionHandler = null; inheritedTenantContainer = null; + resourceContainer = null; + inheritedResourceContainer = null; } /** diff --git a/src/share/classes/sun/misc/JavaLangAccess.java b/src/share/classes/sun/misc/JavaLangAccess.java index ec55a29e6fdf775b287770936490eeb6f2561e62..04494e668f89c6eddd084b2c5c831a222eea48a2 100644 --- a/src/share/classes/sun/misc/JavaLangAccess.java +++ b/src/share/classes/sun/misc/JavaLangAccess.java @@ -145,4 +145,9 @@ public interface JavaLangAccess { * Get the reference to the thread attached {@code ResourceContainer} */ AbstractResourceContainer getResourceContainer(Thread thread); + + /** + * Get the reference to the thread's inherited {@code ResourceContainer} + */ + AbstractResourceContainer getInheritedResourceContainer(Thread thread); } diff --git a/test/com/alibaba/rcm/TestConfiguration.java b/test/com/alibaba/rcm/TestConfiguration.java index b6d4609733f4184b3cb11b04c396df2ea117330e..bcaea5fa97fcd5949369d7e22542792af2bf81c8 100644 --- a/test/com/alibaba/rcm/TestConfiguration.java +++ b/test/com/alibaba/rcm/TestConfiguration.java @@ -46,14 +46,16 @@ public class TestConfiguration { MyResourceType.MY_RESOURCE1.newConstraint(), MyResourceType.MY_RESOURCE2.newConstraint())); - assertTrue(iterator2Stream(mc.operations.iterator()).collect(Collectors.toSet()) - .equals(new HashSet<>(Arrays.asList("update MY_RESOURCE1", "update MY_RESOURCE2")))); + .equals(new HashSet<>(Arrays.asList("update " + MyResourceType.MY_RESOURCE1.toString(), + "update " + MyResourceType.MY_RESOURCE2.toString())))); mc.updateConstraint(MyResourceType.MY_RESOURCE2.newConstraint()); assertTrue(iterator2Stream(mc.operations.iterator()).collect(Collectors.toSet()) - .equals(new HashSet<>(Arrays.asList("update MY_RESOURCE1", "update MY_RESOURCE2", "update MY_RESOURCE2")))); + .equals(new HashSet<>(Arrays.asList("update " + MyResourceType.MY_RESOURCE1.toString(), + "update " + MyResourceType.MY_RESOURCE2.toString(), + "update " + MyResourceType.MY_RESOURCE2.toString())))); } private static Stream iterator2Stream(Iterator iterator) { diff --git a/test/com/alibaba/rcm/TestInherit.java b/test/com/alibaba/rcm/TestInherit.java index d4f30c19a15cd0c0128ae7f549e2bbfbf1fe3ccd..f6586f56b2c6878230f89e009d81797ca856b2bd 100644 --- a/test/com/alibaba/rcm/TestInherit.java +++ b/test/com/alibaba/rcm/TestInherit.java @@ -28,6 +28,7 @@ */ import com.alibaba.rcm.ResourceContainer; +import demo.RCInheritedThreadFactory; import demo.MyResourceFactory; import java.util.Collections; @@ -44,23 +45,23 @@ public class TestInherit { rc.run(() -> { assertEQ(ResourceContainer.current(), rc); FutureTask f1 = new FutureTask<>(ResourceContainer::current); - new Thread(f1).start(); + RCInheritedThreadFactory.INSTANCE.newThread(f1).start(); assertEQ(get(f1), rc); FutureTask f2 = new FutureTask<>(ResourceContainer::current); - ResourceContainer.root().run(() -> new Thread(f2).start()); + ResourceContainer.root().run(() -> RCInheritedThreadFactory.INSTANCE.newThread(f2).start()); assertEQ(get(f2), ResourceContainer.root()); }); // thread is bound to it's parent thread(the thread called Thread::init()) // not dependent on where Thread::start() called. FutureTask f3 = new FutureTask<>(ResourceContainer::current); - Thread t3 = new Thread(f3); + Thread t3 = RCInheritedThreadFactory.INSTANCE.newThread(f3); // Thread::init is called in root() rc.run(t3::start); assertEQ(get(f3), ResourceContainer.root()); FutureTask f4 = new FutureTask<>(ResourceContainer::current); - FutureTask newThread = new FutureTask<>(() -> new Thread(f4)); + FutureTask newThread = new FutureTask<>(() -> RCInheritedThreadFactory.INSTANCE.newThread(f4)); // Thread::init is called in container rc.run(newThread); get(newThread).start(); diff --git a/test/com/alibaba/rcm/TestInheritedContainer.java b/test/com/alibaba/rcm/TestInheritedContainer.java new file mode 100644 index 0000000000000000000000000000000000000000..7ba630e0c12aa7482d3c67cb42af69aef7b004f4 --- /dev/null +++ b/test/com/alibaba/rcm/TestInheritedContainer.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Alibaba designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * @test + * @summary Test ONLY inheritedResourceContainer is inherited from parent + * @library /lib/testlibrary + * @run main TestInheritedContainer + */ + +import com.alibaba.rcm.ResourceContainer; +import demo.MyResourceFactory; +import sun.misc.JavaLangAccess; +import sun.misc.SharedSecrets; + +import java.util.Collections; +import java.util.concurrent.CompletableFuture; + +import static jdk.testlibrary.Asserts.assertEQ; + + +public class TestInheritedContainer { + public static void main(String[] args) throws Exception { + ResourceContainer rc = MyResourceFactory.INSTANCE.createContainer(Collections.emptyList()); + JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + rc.run(() -> { + try { + assertEQ(ResourceContainer.root(), + CompletableFuture.supplyAsync(() -> JLA.getResourceContainer(Thread.currentThread())).get()); + assertEQ(rc, + CompletableFuture.supplyAsync(() -> JLA.getInheritedResourceContainer(Thread.currentThread())).get()); + } catch (Exception e) { + throw new AssertionError(e); + } + }); + } +} diff --git a/test/com/alibaba/rcm/TestRootNotNull.java b/test/com/alibaba/rcm/TestRootNotNull.java new file mode 100644 index 0000000000000000000000000000000000000000..be5c11790e17099c0e66fd9bb5b1815b9ec5030d --- /dev/null +++ b/test/com/alibaba/rcm/TestRootNotNull.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Alibaba designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * @test + * @summary Test default ResourceContainer is root() instead of null + * @library /lib/testlibrary + * @run main TestRootNotNull + */ + +import sun.misc.SharedSecrets; + +import static jdk.testlibrary.Asserts.assertNotNull; + +public class TestRootNotNull { + public static void main(String[] args) { + assertNotNull(SharedSecrets.getJavaLangAccess().getResourceContainer(Thread.currentThread())); + } +} diff --git a/test/com/alibaba/rcm/demo/RCInheritedThreadFactory.java b/test/com/alibaba/rcm/demo/RCInheritedThreadFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..805cff8d02e85df4a7d47514481838d79a45f8f8 --- /dev/null +++ b/test/com/alibaba/rcm/demo/RCInheritedThreadFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Alibaba designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package demo; + +import com.alibaba.rcm.internal.AbstractResourceContainer; +import sun.misc.JavaLangAccess; +import sun.misc.SharedSecrets; + +import java.util.concurrent.ThreadFactory; + +public class RCInheritedThreadFactory implements ThreadFactory { + public final static ThreadFactory INSTANCE = new RCInheritedThreadFactory(); + private final static JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + + @Override + public Thread newThread(Runnable r) { + return new Thread(() -> { + AbstractResourceContainer irc = JLA.getInheritedResourceContainer(Thread.currentThread()); + if (irc != null) { + irc.run(r); + } else { + r.run(); + } + }); + } +}