This commit is contained in:
Jesper Wilhelmsson 2022-06-16 12:01:32 +00:00
commit 3d12c0225b
17 changed files with 240 additions and 60 deletions

View file

@ -1298,20 +1298,27 @@ void LIRGenerator::do_getModifiers(Intrinsic* x) {
info = state_for(x); info = state_for(x);
} }
LabelObj* L_not_prim = new LabelObj(); // While reading off the universal constant mirror is less efficient than doing
LabelObj* L_done = new LabelObj(); // another branch and returning the constant answer, this branchless code runs into
// much less risk of confusion for C1 register allocator. The choice of the universe
// object here is correct as long as it returns the same modifiers we would expect
// from the primitive class itself. See spec for Class.getModifiers that provides
// the typed array klasses with similar modifiers as their component types.
Klass* univ_klass_obj = Universe::byteArrayKlassObj();
assert(univ_klass_obj->modifier_flags() == (JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC), "Sanity");
LIR_Opr prim_klass = LIR_OprFact::metadataConst(univ_klass_obj);
LIR_Opr recv_klass = new_register(T_METADATA);
__ move(new LIR_Address(receiver.result(), java_lang_Class::klass_offset(), T_ADDRESS), recv_klass, info);
// Check if this is a Java mirror of primitive type, and select the appropriate klass.
LIR_Opr klass = new_register(T_METADATA); LIR_Opr klass = new_register(T_METADATA);
// Checking if it's a java mirror of primitive type __ cmp(lir_cond_equal, recv_klass, LIR_OprFact::metadataConst(0));
__ move(new LIR_Address(receiver.result(), java_lang_Class::klass_offset(), T_ADDRESS), klass, info); __ cmove(lir_cond_equal, prim_klass, recv_klass, klass, T_ADDRESS);
__ cmp(lir_cond_notEqual, klass, LIR_OprFact::metadataConst(0));
__ branch(lir_cond_notEqual, L_not_prim->label());
__ move(LIR_OprFact::intConst(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC), result);
__ branch(lir_cond_always, L_done->label());
__ branch_destination(L_not_prim->label()); // Get the answer.
__ move(new LIR_Address(klass, in_bytes(Klass::modifier_flags_offset()), T_INT), result); __ move(new LIR_Address(klass, in_bytes(Klass::modifier_flags_offset()), T_INT), result);
__ branch_destination(L_done->label());
} }
void LIRGenerator::do_getObjectSize(Intrinsic* x) { void LIRGenerator::do_getObjectSize(Intrinsic* x) {

View file

@ -619,8 +619,10 @@ bool ciInstanceKlass::is_leaf_type() {
ciInstanceKlass* ciInstanceKlass::implementor() { ciInstanceKlass* ciInstanceKlass::implementor() {
ciInstanceKlass* impl = _implementor; ciInstanceKlass* impl = _implementor;
if (impl == NULL) { if (impl == NULL) {
if (is_shared()) {
impl = this; // assume a well-known interface never has a unique implementor
} else {
// Go into the VM to fetch the implementor. // Go into the VM to fetch the implementor.
{
VM_ENTRY_MARK; VM_ENTRY_MARK;
MutexLocker ml(Compile_lock); MutexLocker ml(Compile_lock);
Klass* k = get_instanceKlass()->implementor(); Klass* k = get_instanceKlass()->implementor();
@ -634,10 +636,8 @@ ciInstanceKlass* ciInstanceKlass::implementor() {
} }
} }
// Memoize this result. // Memoize this result.
if (!is_shared()) {
_implementor = impl; _implementor = impl;
} }
}
return impl; return impl;
} }

View file

@ -661,7 +661,8 @@ public:
VM_VirtualThreadGetStackTrace(JvmtiEnv *env, Handle vthread_h, VM_VirtualThreadGetStackTrace(JvmtiEnv *env, Handle vthread_h,
jint start_depth, jint max_count, jint start_depth, jint max_count,
jvmtiFrameInfo* frame_buffer, jint* count_ptr) jvmtiFrameInfo* frame_buffer, jint* count_ptr)
: _vthread_h(vthread_h), : _env(env),
_vthread_h(vthread_h),
_start_depth(start_depth), _start_depth(start_depth),
_max_count(max_count), _max_count(max_count),
_frame_buffer(frame_buffer), _frame_buffer(frame_buffer),
@ -683,7 +684,8 @@ private:
public: public:
VM_VirtualThreadGetFrameCount(JvmtiEnv *env, Handle vthread_h, jint* count_ptr) VM_VirtualThreadGetFrameCount(JvmtiEnv *env, Handle vthread_h, jint* count_ptr)
: _vthread_h(vthread_h), : _env(env),
_vthread_h(vthread_h),
_count_ptr(count_ptr), _count_ptr(count_ptr),
_result(JVMTI_ERROR_NONE) _result(JVMTI_ERROR_NONE)
{} {}

View file

@ -1926,7 +1926,7 @@ public final class Long extends Number
* value: * value:
* {@snippet lang="java" : * {@snippet lang="java" :
* // Compressing drink to food * // Compressing drink to food
* compress(0xCAFEBABE, 0xFF00FFF0) == 0xCABAB * compress(0xCAFEBABEL, 0xFF00FFF0L) == 0xCABABL
* } * }
* Starting from the least significant hexadecimal digit at position 0 * Starting from the least significant hexadecimal digit at position 0
* from the right, the mask {@code 0xFF00FFF0} selects hexadecimal digits * from the right, the mask {@code 0xFF00FFF0} selects hexadecimal digits
@ -1938,16 +1938,16 @@ public final class Long extends Number
* understand the behaviour of {@code compress}: * understand the behaviour of {@code compress}:
* {@snippet lang="java" : * {@snippet lang="java" :
* // Returns 1 if the bit at position n is one * // Returns 1 if the bit at position n is one
* compress(x, 1 << n) == (x >> n & 1) * compress(x, 1L << n) == (x >> n & 1)
* *
* // Logical shift right * // Logical shift right
* compress(x, -1 << n) == x >>> n * compress(x, -1L << n) == x >>> n
* *
* // Any bits not covered by the mask are ignored * // Any bits not covered by the mask are ignored
* compress(x, m) == compress(x & m, m) * compress(x, m) == compress(x & m, m)
* *
* // Compressing a value by itself * // Compressing a value by itself
* compress(m, m) == (m == -1 || m == 0) ? m : (1 << bitCount(m)) - 1 * compress(m, m) == (m == -1 || m == 0) ? m : (1L << bitCount(m)) - 1
* *
* // Expanding then compressing with the same mask * // Expanding then compressing with the same mask
* compress(expand(x, m), m) == x & compress(m, m) * compress(expand(x, m), m) == x & compress(m, m)
@ -1969,7 +1969,7 @@ public final class Long extends Number
* } * }
* *
* // Separate the sheep from the goats * // Separate the sheep from the goats
* sag(0xCAFEBABE, 0xFF00FFF0) == 0xCABABFEE * sag(0x00000000_CAFEBABEL, 0xFFFFFFFF_FF00FFF0L) == 0x00000000_CABABFEEL
* } * }
* *
* @param i the value whose bits are to be compressed * @param i the value whose bits are to be compressed
@ -2018,7 +2018,7 @@ public final class Long extends Number
* Consider the simple case of expanding the digits of a hexadecimal * Consider the simple case of expanding the digits of a hexadecimal
* value: * value:
* {@snippet lang="java" : * {@snippet lang="java" :
* expand(0x0000CABAB, 0xFF00FFF0) == 0xCA00BAB0 * expand(0x0000CABABL, 0xFF00FFF0L) == 0xCA00BAB0L
* } * }
* Starting from the least significant hexadecimal digit at position 0 * Starting from the least significant hexadecimal digit at position 0
* from the right, the mask {@code 0xFF00FFF0} selects the first five * from the right, the mask {@code 0xFF00FFF0} selects the first five
@ -2029,13 +2029,13 @@ public final class Long extends Number
* understand the behaviour of {@code expand}: * understand the behaviour of {@code expand}:
* {@snippet lang="java" : * {@snippet lang="java" :
* // Logically shift right the bit at position 0 * // Logically shift right the bit at position 0
* expand(x, 1 << n) == (x & 1) << n * expand(x, 1L << n) == (x & 1) << n
* *
* // Logically shift right * // Logically shift right
* expand(x, -1 << n) == x << n * expand(x, -1L << n) == x << n
* *
* // Expanding all bits returns the mask * // Expanding all bits returns the mask
* expand(-1, m) == m * expand(-1L, m) == m
* *
* // Any bits not covered by the mask are ignored * // Any bits not covered by the mask are ignored
* expand(x, m) == expand(x, m) & m * expand(x, m) == expand(x, m) & m
@ -2049,7 +2049,7 @@ public final class Long extends Number
* {@snippet lang="java" : * {@snippet lang="java" :
* long select(long i, long n) { * long select(long i, long n) {
* // the one-bit in i (the mask) with index n * // the one-bit in i (the mask) with index n
* long nthBit = Long.expand(1 << n, i); * long nthBit = Long.expand(1L << n, i);
* // the bit position of the one-bit with index n * // the bit position of the one-bit with index n
* return Long.numberOfTrailingZeros(nthBit); * return Long.numberOfTrailingZeros(nthBit);
* } * }

View file

@ -1219,10 +1219,9 @@ public final class Files {
* <tbody> * <tbody>
* <tr> * <tr>
* <th scope="row"> {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} </th> * <th scope="row"> {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} </th>
* <td> If the target file exists, then the target file is replaced if it * <td> Replace an existing file. A non-empty directory cannot be
* is not a non-empty directory. If the target file exists and is a * replaced. If the target file exists and is a symbolic link, then the
* symbolic link, then the symbolic link itself, not the target of * symbolic link itself, not the target of the link, is replaced. </td>
* the link, is replaced. </td>
* </tr> * </tr>
* <tr> * <tr>
* <th scope="row"> {@link StandardCopyOption#COPY_ATTRIBUTES COPY_ATTRIBUTES} </th> * <th scope="row"> {@link StandardCopyOption#COPY_ATTRIBUTES COPY_ATTRIBUTES} </th>
@ -1342,10 +1341,9 @@ public final class Files {
* <tbody> * <tbody>
* <tr> * <tr>
* <th scope="row"> {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} </th> * <th scope="row"> {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} </th>
* <td> If the target file exists, then the target file is replaced if it * <td> Replace an existing file. A non-empty directory cannot be
* is not a non-empty directory. If the target file exists and is a * replaced. If the target file exists and is a symbolic link, then the
* symbolic link, then the symbolic link itself, not the target of * symbolic link itself, not the target of the link, is replaced. </td>
* the link, is replaced. </td>
* </tr> * </tr>
* <tr> * <tr>
* <th scope="row"> {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} </th> * <th scope="row"> {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} </th>

View file

@ -35,6 +35,12 @@ import com.sun.source.doctree.DocTree;
* Inside your method, call super.visitXYZ to visit descendant * Inside your method, call super.visitXYZ to visit descendant
* nodes. * nodes.
* *
* @param <R> the return type of this visitor's methods. Use {@link
* Void} for visitors that do not need to return results.
* @param <P> the type of the additional parameter to this visitor's
* methods. Use {@code Void} for visitors that do not need an
* additional parameter.
*
* @since 1.8 * @since 1.8
*/ */
public class DocTreePathScanner<R, P> extends DocTreeScanner<R, P> { public class DocTreePathScanner<R, P> extends DocTreeScanner<R, P> {

View file

@ -66,6 +66,12 @@ import com.sun.source.doctree.*;
* the last child scanned. * the last child scanned.
* </ul> * </ul>
* *
* @param <R> the return type of this visitor's methods. Use {@link
* Void} for visitors that do not need to return results.
* @param <P> the type of the additional parameter to this visitor's
* methods. Use {@code Void} for visitors that do not need an
* additional parameter.
*
* @since 1.8 * @since 1.8
*/ */
public class DocTreeScanner<R,P> implements DocTreeVisitor<R,P> { public class DocTreeScanner<R,P> implements DocTreeVisitor<R,P> {

View file

@ -39,6 +39,12 @@ import com.sun.source.tree.*;
* In order to initialize the "current path", the scan must be * In order to initialize the "current path", the scan must be
* started by calling one of the {@code scan} methods. * started by calling one of the {@code scan} methods.
* *
* @param <R> the return type of this visitor's methods. Use {@link
* Void} for visitors that do not need to return results.
* @param <P> the type of the additional parameter to this visitor's
* methods. Use {@code Void} for visitors that do not need an
* additional parameter.
*
* @author Jonathan Gibbons * @author Jonathan Gibbons
* @since 1.6 * @since 1.6
*/ */

View file

@ -518,7 +518,7 @@ public interface ThreadReference extends ObjectReference {
* *
* @since 19 * @since 19
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) @PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS, reflective = true)
default boolean isVirtual() { default boolean isVirtual() {
throw new UnsupportedOperationException("Method not implemented"); throw new UnsupportedOperationException("Method not implemented");
} }

View file

@ -72,7 +72,7 @@ public interface ThreadDeathRequest extends EventRequest {
* *
* @since 19 * @since 19
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) @PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS, reflective = true)
default void addPlatformThreadsOnlyFilter() { default void addPlatformThreadsOnlyFilter() {
throw new UnsupportedOperationException("Method not implemented"); throw new UnsupportedOperationException("Method not implemented");
} }

View file

@ -72,7 +72,7 @@ public interface ThreadStartRequest extends EventRequest {
* *
* @since 19 * @since 19
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) @PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS, reflective = true)
default void addPlatformThreadsOnlyFilter() { default void addPlatformThreadsOnlyFilter() {
throw new UnsupportedOperationException("Method not implemented"); throw new UnsupportedOperationException("Method not implemented");
} }

View file

@ -110,7 +110,7 @@ public final class RecordedThread extends RecordedObject {
* *
* @since 19 * @since 19
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) @PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS, reflective = true)
public boolean isVirtual() { public boolean isVirtual() {
return getTyped("virtual", Boolean.class, Boolean.FALSE); return getTyped("virtual", Boolean.class, Boolean.FALSE);
} }

View file

@ -149,7 +149,7 @@ public interface HotSpotDiagnosticMXBean extends PlatformManagedObject {
* @throws UnsupportedOperationException if this operation is not supported * @throws UnsupportedOperationException if this operation is not supported
* @since 19 * @since 19
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) @PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS, reflective = true)
default void dumpThreads(String outputFile, ThreadDumpFormat format) throws IOException { default void dumpThreads(String outputFile, ThreadDumpFormat format) throws IOException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -158,7 +158,7 @@ public interface HotSpotDiagnosticMXBean extends PlatformManagedObject {
* Thread dump format. * Thread dump format.
* @since 19 * @since 19
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) @PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS, reflective = true)
public static enum ThreadDumpFormat { public static enum ThreadDumpFormat {
/** /**
* Plain text format. * Plain text format.

View file

@ -83,6 +83,7 @@ gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all
gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all
gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64 gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64
gc/stress/TestStressG1Humongous.java 8286554 windows-x64
############################################################################# #############################################################################
@ -120,8 +121,6 @@ serviceability/sa/ClhsdbPstack.java#core 8269982,8267433 macosx-aarch64,macosx-x
serviceability/sa/TestJmapCore.java 8269982,8267433 macosx-aarch64,macosx-x64 serviceability/sa/TestJmapCore.java 8269982,8267433 macosx-aarch64,macosx-x64
serviceability/sa/TestJmapCoreMetaspace.java 8269982,8267433 macosx-aarch64,macosx-x64 serviceability/sa/TestJmapCoreMetaspace.java 8269982,8267433 macosx-aarch64,macosx-x64
serviceability/jvmti/vthread/VThreadNotifyFramePopTest/VThreadNotifyFramePopTest.java 8288214 generic-all
############################################################################# #############################################################################
# :hotspot_misc # :hotspot_misc

View file

@ -0,0 +1,118 @@
/*
* Copyright (c) 2022, Red Hat, Inc. 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.
*
* 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.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @library /test/lib
* @run main/othervm -Xint
* -XX:CompileCommand=dontinline,*TestGetModifiers.test
* compiler.intrinsics.klass.TestGetModifiers
*/
/*
* @test
* @requires vm.compiler1.enabled
* @library /test/lib
* @run main/othervm -XX:TieredStopAtLevel=1 -XX:+TieredCompilation
* -XX:CompileCommand=dontinline,*TestGetModifiers.test
* compiler.intrinsics.klass.TestGetModifiers
*/
/*
* @test
* @requires vm.compiler2.enabled
* @library /test/lib
* @run main/othervm -XX:-TieredCompilation
* -XX:CompileCommand=dontinline,*TestGetModifiers.test
* compiler.intrinsics.klass.TestGetModifiers
*/
package compiler.intrinsics.klass;
import java.lang.reflect.Modifier;
import static java.lang.reflect.Modifier.*;
import jdk.test.lib.Asserts;
public class TestGetModifiers {
public static class T1 {
}
public static final class T2 {
}
private static class T3 {
}
protected static class T4 {
}
class T5 {
}
interface T6 {
}
static void test(Class cl, int expectedMods) {
for (int i = 0; i < 100_000; i++) {
int actualMods = cl.getModifiers();
if (actualMods != expectedMods) {
throw new IllegalStateException("Error with: " + cl);
}
}
}
public static void main(String... args) {
test(T1.class, PUBLIC | STATIC);
test(T2.class, PUBLIC | FINAL | STATIC);
test(T3.class, PRIVATE | STATIC);
test(T4.class, PROTECTED | STATIC);
test(new TestGetModifiers().new T5().getClass(), 0);
test(T6.class, ABSTRACT | STATIC | INTERFACE);
test(int.class, PUBLIC | ABSTRACT | FINAL);
test(long.class, PUBLIC | ABSTRACT | FINAL);
test(double.class, PUBLIC | ABSTRACT | FINAL);
test(float.class, PUBLIC | ABSTRACT | FINAL);
test(char.class, PUBLIC | ABSTRACT | FINAL);
test(byte.class, PUBLIC | ABSTRACT | FINAL);
test(short.class, PUBLIC | ABSTRACT | FINAL);
test(void.class, PUBLIC | ABSTRACT | FINAL);
test(int[].class, PUBLIC | ABSTRACT | FINAL);
test(long[].class, PUBLIC | ABSTRACT | FINAL);
test(double[].class, PUBLIC | ABSTRACT | FINAL);
test(float[].class, PUBLIC | ABSTRACT | FINAL);
test(char[].class, PUBLIC | ABSTRACT | FINAL);
test(byte[].class, PUBLIC | ABSTRACT | FINAL);
test(short[].class, PUBLIC | ABSTRACT | FINAL);
test(Object[].class, PUBLIC | ABSTRACT | FINAL);
test(TestGetModifiers[].class, PUBLIC | ABSTRACT | FINAL);
test(new TestGetModifiers().getClass(), PUBLIC);
test(new T1().getClass(), PUBLIC | STATIC);
test(new T2().getClass(), PUBLIC | FINAL | STATIC);
test(new T3().getClass(), PRIVATE | STATIC);
test(new T4().getClass(), PROTECTED | STATIC);
}
}

View file

@ -23,11 +23,13 @@
/** /**
* @test * @test
* @bug 8284161 8288214
* @summary Verifies that FRAME_POP event is delivered when called from URL.openStream(). * @summary Verifies that FRAME_POP event is delivered when called from URL.openStream().
* @requires vm.continuations * @requires vm.continuations
* @compile --enable-preview -source ${jdk.version} VThreadNotifyFramePopTest.java * @enablePreview
* @modules jdk.httpserver
* @library /test/lib
* @run main/othervm/native * @run main/othervm/native
* --enable-preview
* -agentlib:VThreadNotifyFramePopTest * -agentlib:VThreadNotifyFramePopTest
* -Djdk.defaultScheduler.parallelism=2 -Djdk.defaultScheduler.maxPoolSize=2 * -Djdk.defaultScheduler.parallelism=2 -Djdk.defaultScheduler.maxPoolSize=2
* VThreadNotifyFramePopTest * VThreadNotifyFramePopTest
@ -35,8 +37,8 @@
/* /*
* This test reproduces a bug with NotifyFramePop not working properly when called * This test reproduces a bug with NotifyFramePop not working properly when called
* from URL.openStream() while executing on a VThread. The FRAME_POP event is never * from URL.openStream() while executing on a virtual thread. The FRAME_POP event is
* delivered. * never delivered.
* *
* The test first sets up a breakpoint on URL.openStream(). Once it is hit the test * The test first sets up a breakpoint on URL.openStream(). Once it is hit the test
* does a NotifyFramePop on the current frame, and also sets up a breakpoint on * does a NotifyFramePop on the current frame, and also sets up a breakpoint on
@ -44,12 +46,17 @@
* returns. The expaction is that the FRAME_POP event should be delevered before * returns. The expaction is that the FRAME_POP event should be delevered before
* hitting the breakpoint in brkpoint(). * hitting the breakpoint in brkpoint().
*/ */
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.URL; import java.net.URL;
import java.time.Duration; import java.time.Duration;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import com.sun.net.httpserver.HttpServer;
import jdk.test.lib.net.URIBuilder;
public class VThreadNotifyFramePopTest { public class VThreadNotifyFramePopTest {
private static final String agentLib = "VThreadNotifyFramePopTest"; private static final String agentLib = "VThreadNotifyFramePopTest";
@ -57,6 +64,24 @@ public class VThreadNotifyFramePopTest {
static native void enableEvents(Thread thread, Class testClass, Class urlClass); static native void enableEvents(Thread thread, Class testClass, Class urlClass);
static native boolean check(); static native boolean check();
/**
* Creates a HTTP server bound to the loopback address. The server responds to
* the request "/hello" with a message.
*/
static HttpServer createHttpServer() throws IOException {
InetAddress lb = InetAddress.getLoopbackAddress();
HttpServer server = HttpServer.create(new InetSocketAddress(lb, 0), 16);
server.createContext("/hello", e -> {
byte[] response = "Hello".getBytes("UTF-8");
e.sendResponseHeaders(200, response.length);
try (OutputStream out = e.getResponseBody()) {
out.write(response);
}
});
return server;
}
static int brkpoint() { static int brkpoint() {
return 5; return 5;
} }
@ -71,25 +96,37 @@ public class VThreadNotifyFramePopTest {
} }
static void run4() { static void run4() {
try { try {
URL url = URI.create("http://openjdk.java.net/").toURL(); HttpServer server = createHttpServer();
server.start();
try {
URL url = URIBuilder.newBuilder()
.scheme("http")
.loopback()
.port(server.getAddress().getPort())
.path("/hello")
.toURL();
System.out.println("open " + url);
try (InputStream in = url.openStream()) { try (InputStream in = url.openStream()) {
brkpoint(); brkpoint();
System.out.println("reading response");
in.readAllBytes(); in.readAllBytes();
System.out.println("readAllBytes done");
} }
System.out.println("try done"); } finally {
System.out.println("stop server");
server.stop(1);
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throw new RuntimeException(e);
} }
System.out.println("run done"); System.out.println("run done");
} }
void runTest() throws Exception { void runTest() throws Exception {
enableEvents(Thread.currentThread(), VThreadNotifyFramePopTest.class, URL.class); enableEvents(Thread.currentThread(), VThreadNotifyFramePopTest.class, URL.class);
ThreadFactory factory = Thread.ofVirtual().factory(); try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { var future = executor.submit(VThreadNotifyFramePopTest::run);
executor.submit(VThreadNotifyFramePopTest::run); System.out.println("virtual thread started");
System.out.println("submit done"); future.get();
} }
System.out.println("Step::main done"); System.out.println("Step::main done");
} }

View file

@ -30,3 +30,4 @@
java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all
java/lang/ref/ReferenceEnqueue.java 8284236 generic-all java/lang/ref/ReferenceEnqueue.java 8284236 generic-all
java/lang/ref/OOMEInReferenceHandler.java 8066859 generic-all java/lang/ref/OOMEInReferenceHandler.java 8066859 generic-all
java/lang/reflect/callerCache/ReflectionCallerCacheTest.java 8288286 macosx-x64,windows-x64