public static void main(String args[]) throws Exception { Unsafe unsafe = Utils.getUnsafe(); // Allocate a byte, write to the location and read back the value long address = unsafe.allocateMemory(1); assertNotEquals(address, 0L); unsafe.putByte(address, Byte.MAX_VALUE); assertEquals(Byte.MAX_VALUE, unsafe.getByte(address)); unsafe.freeMemory(address); // Call to allocateMemory() with a negative value should result in an IllegalArgumentException try { address = unsafe.allocateMemory(-1); throw new RuntimeException("Did not get expected IllegalArgumentException"); } catch (IllegalArgumentException e) { // Expected assertNotEquals(address, 0L); } // allocateMemory() should throw an OutOfMemoryError when the underlying malloc fails, // we test this by limiting the malloc using -XX:MallocMaxTestWords try { address = unsafe.allocateMemory(100 * 1024 * 1024 * 8); } catch (OutOfMemoryError e) { // Expected return; } throw new RuntimeException("Did not get expected OutOfMemoryError"); }
private void runTest(TestCase tcase) { System.out.println(tcase); HotSpotResolvedObjectType resolvedIface = CompilerToVMHelper.lookupType( Utils.toJVMTypeSignature(tcase.anInterface), getClass(), /* resolve = */ true); HotSpotResolvedObjectType resolvedImplementer = CompilerToVMHelper.getImplementor(resolvedIface); HotSpotResolvedObjectType resolvedExpected = null; if (tcase.expectedImplementer != null) { resolvedExpected = CompilerToVMHelper.lookupType( Utils.toJVMTypeSignature(tcase.expectedImplementer), getClass(), /* resolve = */ true); } Asserts.assertEQ( resolvedImplementer, resolvedExpected, "Unexpected implementer for " + tcase.anInterface.getName()); }
private void checkSanity(CompileCodeTestCase testCase) { System.out.println(testCase); // to have a clean state testCase.deoptimize(); Pair<Object, ? extends Throwable> reflectionResult; Object[] args = Utils.getNullValues(testCase.executable.getParameterTypes()); reflectionResult = testCase.invoke(args); NMethod nMethod = testCase.compile(); if (nMethod == null) { throw new Error(testCase + " : nmethod is null"); } InstalledCode installedCode = testCase.toInstalledCode(); Object result = null; Throwable expectedException = reflectionResult.second; boolean gotException = true; try { args = addReceiver(testCase, args); result = CompilerToVMHelper.executeInstalledCode(args, installedCode); if (testCase.executable instanceof Constructor) { // <init> doesn't have return value, it changes receiver result = args[0]; } gotException = false; } catch (InvalidInstalledCodeException e) { throw new AssertionError(testCase + " : unexpected InvalidInstalledCodeException", e); } catch (Throwable t) { if (expectedException == null) { throw new AssertionError(testCase + " : got unexpected execption : " + t.getMessage(), t); } if (expectedException.getClass() != t.getClass()) { System.err.println("exception from CompilerToVM:"); t.printStackTrace(); System.err.println("exception from reflection:"); expectedException.printStackTrace(); throw new AssertionError( String.format( "%s : got unexpected different exceptions : %s != %s", testCase, expectedException.getClass(), t.getClass())); } } Asserts.assertEQ(reflectionResult.first, result, testCase + " : different return value"); if (!gotException) { Asserts.assertNull(expectedException, testCase + " : expected exception hasn't been thrown"); } }
public void run() { System.setSecurityManager(getSecurityManager()); Consumer<Throwable> exceptionCheck = e -> { if (e == null) { if (getExpectedException() != null) { String message = name() + ": Didn't get expected exception " + getExpectedException(); throw new AssertionError(message); } } else { String message = name() + ": Got unexpected exception " + e.getClass().getSimpleName(); if (getExpectedException() == null) { throw new AssertionError(message, e); } Throwable t = e; while (t.getCause() != null) { t = t.getCause(); } if (!getExpectedException().isAssignableFrom(t.getClass())) { message += " instead of " + getExpectedException().getSimpleName(); throw new AssertionError(message, e); } } }; Utils.runAndCheckException( () -> { try { // CompilerToVM::<cinit> provokes CompilerToVM::<init> Class.forName("jdk.vm.ci.hotspot.CompilerToVMHelper"); } catch (ClassNotFoundException e) { throw new Error("TESTBUG : " + e, e); } }, exceptionCheck); }
private void checkNull() { Utils.runAndCheckException( () -> CompilerToVMHelper.invalidateInstalledCode(null), NullPointerException.class); }
public class ConcurrentClassLoadingTest { int numThreads = 0; CyclicBarrier l; private static final Random rand = Utils.getRandomInstance(); public static void main(String[] args) throws Throwable { ConcurrentClassLoadingTest test = new ConcurrentClassLoadingTest(); test.parseArgs(args); test.run(); } void parseArgs(String[] args) { int i = 0; while (i < args.length) { String flag = args[i]; switch (flag) { case "-numThreads": numThreads = Integer.parseInt(args[++i]); break; default: throw new Error("Unknown flag: " + flag); } ++i; } } void init() { if (numThreads == 0) { numThreads = Runtime.getRuntime().availableProcessors(); } l = new CyclicBarrier(numThreads + 1); System.out.printf("Threads: %d\n", numThreads); } final List<Loader> loaders = new ArrayList<>(); void prepare() { List<String> c = new ArrayList<>(Arrays.asList(classNames)); // Split classes between loading threads int count = (classNames.length / numThreads) + 1; for (int t = 0; t < numThreads; t++) { List<String> sel = new ArrayList<>(); System.out.printf("Thread #%d:\n", t); for (int i = 0; i < count; i++) { if (c.isEmpty()) { break; } int k = rand.nextInt(c.size()); String elem = c.remove(k); sel.add(elem); System.out.printf("\t%s\n", elem); } loaders.add(new Loader(sel)); } // Print diagnostic info when the test hangs Runtime.getRuntime() .addShutdownHook( new Thread() { public void run() { boolean alive = false; for (Loader l : loaders) { if (!l.isAlive()) continue; if (!alive) { System.out.println("Some threads are still alive:"); alive = true; } System.out.println(l.getName()); for (StackTraceElement elem : l.getStackTrace()) { System.out.println("\t" + elem.toString()); } } } }); } public void run() throws Throwable { init(); prepare(); for (Loader loader : loaders) { loader.start(); } l.await(); for (Loader loader : loaders) { loader.join(); } } class Loader extends Thread { List<String> classes; public Loader(List<String> classes) { this.classes = classes; setDaemon(true); } @Override public void run() { try { l.await(); for (String name : classes) { Class.forName(name).getName(); } } catch (ClassNotFoundException | BrokenBarrierException | InterruptedException e) { throw new Error(e); } } } static final String[] classNames = { "java.lang.invoke.CallSite", "java.lang.invoke.ConstantCallSite", "java.lang.invoke.LambdaConversionException", "java.lang.invoke.LambdaMetafactory", "java.lang.invoke.MethodHandle", "java.lang.invoke.MethodHandleInfo", "java.lang.invoke.MethodHandleProxies", "java.lang.invoke.MethodHandles", "java.lang.invoke.MethodType", "java.lang.invoke.MutableCallSite", "java.lang.invoke.SerializedLambda", "java.lang.invoke.SwitchPoint", "java.lang.invoke.VolatileCallSite", "java.lang.invoke.WrongMethodTypeException" }; }
/** A test for scale; launch a large number (14) of subprocesses. */ @Test public static void test5() { ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>(); int factor = 2; JavaChild p1 = null; Instant start = Instant.now(); try { p1 = JavaChild.spawnJavaChild("stdin"); ProcessHandle p1Handle = p1.toHandle(); printf("Spawning %d x %d x %d processes, pid: %d%n", factor, factor, factor, p1.getPid()); // Start the first tier of subprocesses p1.sendAction("spawn", factor, "stdin"); // Start the second tier of subprocesses p1.sendAction("child", "spawn", factor, "stdin"); // Start the third tier of subprocesses p1.sendAction("child", "child", "spawn", factor, "stdin"); int newChildren = factor * (1 + factor * (1 + factor)); CountDownLatch spawnCount = new CountDownLatch(newChildren); // Gather the PIDs from the output of the spawning process p1.forEachOutputLine( (s) -> { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("spawn")) { Long child = Long.valueOf(split[2]); Long parent = Long.valueOf(split[0].split(":")[0]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); spawnCount.countDown(); } }); // Wait for all the subprocesses to be listed as started Assert.assertTrue( spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), "Timeout waiting for processes to start"); // Debugging; list descendants that are not expected in processes List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle); long count = descendants.stream().filter(ph -> !processes.containsKey(ph)).count(); if (count > 0) { descendants .stream() .filter(ph -> !processes.containsKey(ph)) .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); ProcessUtil.logTaskList(); Assert.assertEquals(0, count, "Extra processes in descendants"); } Assert.assertEquals(getChildren(p1Handle).size(), factor, "expected direct children"); count = getDescendants(p1Handle).size(); long totalChildren = factor * factor * factor + factor * factor + factor; Assert.assertTrue( count >= totalChildren, "expected at least " + totalChildren + ", actual: " + count); List<ProcessHandle> subprocesses = getDescendants(p1Handle); printf( " descendants: %s%n", subprocesses.stream().map(p -> p.getPid()).collect(Collectors.toList())); p1.getOutputStream().close(); // Close stdin for the controlling p1 p1.waitFor(); } catch (InterruptedException | IOException ex) { Assert.fail("Unexpected Exception", ex); } finally { printf("Duration: %s%n", Duration.between(start, Instant.now())); if (p1 != null) { p1.destroyForcibly(); } processes.forEach( (p, parent) -> { if (p.isAlive()) { ProcessUtil.printProcess(p, "Process Cleanup: "); p.destroyForcibly(); } }); } }
/** * Test destroy of processes. A JavaChild is started and it starts three children. Each one is * then checked to be alive and listed by descendants and forcibly destroyed. After they exit they * should no longer be listed by descendants. */ @Test public static void test3() { ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>(); try { ProcessHandle self = ProcessHandle.current(); JavaChild p1 = JavaChild.spawnJavaChild("stdin"); ProcessHandle p1Handle = p1.toHandle(); printf(" p1: %s%n", p1.getPid()); int newChildren = 3; CountDownLatch spawnCount = new CountDownLatch(newChildren); // Spawn children and have them wait p1.sendAction("spawn", newChildren, "stdin"); // Gather the PIDs from the output of the spawning process p1.forEachOutputLine( (s) -> { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("spawn")) { Long child = Long.valueOf(split[2]); Long parent = Long.valueOf(split[0].split(":")[0]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); spawnCount.countDown(); } }); // Wait for all the subprocesses to be listed as started Assert.assertTrue( spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), "Timeout waiting for processes to start"); // Debugging; list descendants that are not expected in processes List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle); long count = descendants.stream().filter(ph -> !processes.containsKey(ph)).count(); if (count > 0) { descendants .stream() .filter(ph -> !processes.containsKey(ph)) .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); ProcessUtil.logTaskList(); Assert.assertEquals(0, count, "Extra processes in descendants"); } // Verify that all spawned children are alive, show up in the descendants list // then destroy them processes.forEach( (p, parent) -> { Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p); Assert.assertTrue( descendants.contains(p), "Spawned child should be listed in descendants: " + p); p.destroyForcibly(); }); Assert.assertEquals(processes.size(), newChildren, "Wrong number of children"); // Wait for each of the processes to exit processes.forEach( (p, parent) -> { for (long retries = Utils.adjustTimeout(100L); retries > 0; retries--) { if (!p.isAlive()) { return; // not alive, go on to the next } // Wait a bit and retry try { Thread.sleep(100L); } catch (InterruptedException ie) { // try again } } printf( "Timeout waiting for exit of pid %s, parent: %s, info: %s%n", p, parent, p.info()); Assert.fail("Process still alive: " + p); }); p1.destroyForcibly(); p1.waitFor(); // Verify that none of the spawned children are still listed by descendants List<ProcessHandle> remaining = getDescendants(self); Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited"); remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList()); Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining); } catch (IOException ioe) { Assert.fail("Spawn of subprocess failed", ioe); } catch (InterruptedException inte) { Assert.fail("InterruptedException", inte); } finally { processes.forEach( (p, parent) -> { if (p.isAlive()) { ProcessUtil.printProcess(p); p.destroyForcibly(); } }); } }
/** Test counting and spawning and counting of Processes. */ @Test public static void test2() { try { ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>(); ProcessHandle self = ProcessHandle.current(); List<ProcessHandle> initialChildren = getChildren(self); long count = initialChildren.size(); if (count > 0) { initialChildren.forEach(p -> printDeep(p, "test2 initial unexpected: ")); } JavaChild p1 = JavaChild.spawnJavaChild("stdin"); ProcessHandle p1Handle = p1.toHandle(); printf(" p1 pid: %d%n", p1.getPid()); // Gather the PIDs from the output of the spawing process p1.forEachOutputLine( (s) -> { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("spawn")) { Long child = Long.valueOf(split[2]); Long parent = Long.valueOf(split[0].split(":")[0]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); } }); int spawnNew = 3; p1.sendAction("spawn", spawnNew, "stdin"); // Wait for direct children to be created and save the list List<ProcessHandle> subprocesses = waitForAllChildren(p1Handle, spawnNew); Optional<Instant> p1Start = p1Handle.info().startInstant(); for (ProcessHandle ph : subprocesses) { Assert.assertTrue(ph.isAlive(), "Child should be alive: " + ph); // Verify each child was started after the parent ph.info() .startInstant() .ifPresent( childStart -> p1Start.ifPresent( parentStart -> { Assert.assertFalse( childStart.isBefore(parentStart), String.format( "Child process started before parent: child: %s, parent: %s", childStart, parentStart)); })); } // Each child spawns two processes and waits for commands int spawnNewSub = 2; p1.sendAction("child", "spawn", spawnNewSub, "stdin"); // Poll until all 9 child processes exist or the timeout is reached int expected = 9; long timeout = Utils.adjustTimeout(60L); Instant endTimeout = Instant.now().plusSeconds(timeout); do { Thread.sleep(200L); printf(" subprocess count: %d, waiting for %d%n", processes.size(), expected); } while (processes.size() < expected && Instant.now().isBefore(endTimeout)); if (processes.size() < expected) { printf("WARNING: not all children have been started. Can't complete test.%n"); printf(" You can try to increase the timeout or%n"); printf(" you can try to use a faster VM (i.e. not a debug version).%n"); } // show the complete list of children (for debug) List<ProcessHandle> descendants = getDescendants(p1Handle); printf( " descendants: %s%n", descendants.stream().map(p -> p.getPid()).collect(Collectors.toList())); // Verify that all spawned children show up in the descendants List processes.forEach( (p, parent) -> { Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p); Assert.assertTrue( descendants.contains(p), "Spawned child should be listed in descendants: " + p); }); // Closing JavaChild's InputStream will cause all children to exit p1.getOutputStream().close(); for (ProcessHandle p : descendants) { try { p.onExit().get(); // wait for the child to exit } catch (ExecutionException e) { Assert.fail("waiting for process to exit", e); } } p1.waitFor(); // wait for spawned process to exit // Verify spawned processes are no longer alive processes.forEach( (ph, parent) -> Assert.assertFalse(ph.isAlive(), "process should not be alive: " + ph)); } catch (IOException | InterruptedException t) { t.printStackTrace(); throw new RuntimeException(t); } }
/** Tests for jdk.vm.ci.hotspot.CompilerToVM::getConstantPool method */ public class GetConstantPoolTest { private static enum TestCase { NULL_BASE { @Override ConstantPool getConstantPool() { return CompilerToVMHelper.getConstantPool(null, getPtrToCpAddress()); } }, JAVA_METHOD_BASE { @Override ConstantPool getConstantPool() { HotSpotResolvedJavaMethod methodInstance = CompilerToVMHelper.getResolvedJavaMethodAtSlot(TEST_CLASS, 0); Field field; try { // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod field = methodInstance.getClass().getDeclaredField("metaspaceMethod"); field.setAccessible(true); field.set(methodInstance, getPtrToCpAddress()); } catch (ReflectiveOperationException e) { throw new Error("TESTBUG : " + e, e); } return CompilerToVMHelper.getConstantPool(methodInstance, 0L); } }, CONSTANT_POOL_BASE { @Override ConstantPool getConstantPool() { ConstantPool cpInst; try { cpInst = CompilerToVMHelper.getConstantPool(null, getPtrToCpAddress()); Field field = CompilerToVMHelper.HotSpotConstantPoolClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, getPtrToCpAddress()); } catch (ReflectiveOperationException e) { throw new Error("TESTBUG : " + e.getMessage(), e); } return CompilerToVMHelper.getConstantPool(cpInst, 0L); } }, CONSTANT_POOL_BASE_IN_TWO { @Override ConstantPool getConstantPool() { long ptr = getPtrToCpAddress(); ConstantPool cpInst; try { cpInst = CompilerToVMHelper.getConstantPool(null, ptr); Field field = CompilerToVMHelper.HotSpotConstantPoolClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, ptr / 2L); } catch (ReflectiveOperationException e) { throw new Error("TESTBUG : " + e.getMessage(), e); } return CompilerToVMHelper.getConstantPool(cpInst, ptr - ptr / 2L); } }, CONSTANT_POOL_BASE_ZERO { @Override ConstantPool getConstantPool() { long ptr = getPtrToCpAddress(); ConstantPool cpInst; try { cpInst = CompilerToVMHelper.getConstantPool(null, ptr); Field field = CompilerToVMHelper.HotSpotConstantPoolClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, 0L); } catch (ReflectiveOperationException e) { throw new Error("TESTBUG : " + e.getMessage(), e); } return CompilerToVMHelper.getConstantPool(cpInst, ptr); } }, OBJECT_TYPE_BASE { @Override ConstantPool getConstantPool() { HotSpotResolvedObjectType type = HotSpotResolvedObjectType.fromObjectClass(OBJECT_TYPE_BASE.getClass()); long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE); return CompilerToVMHelper.getConstantPool(type, getPtrToCpAddress() - ptrToClass); } }, ; abstract ConstantPool getConstantPool(); } private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final Unsafe UNSAFE = Utils.getUnsafe(); private static final Class TEST_CLASS = GetConstantPoolTest.class; private static final long CP_ADDRESS = WB.getConstantPool(GetConstantPoolTest.class); public void test(TestCase testCase) { System.out.println(testCase.name()); ConstantPool cp = testCase.getConstantPool(); String cpStringRep = cp.toString(); String cpClassSimpleName = CompilerToVMHelper.HotSpotConstantPoolClass().getSimpleName(); if (!cpStringRep.contains(cpClassSimpleName) || !cpStringRep.contains(TEST_CLASS.getName())) { String msg = String.format( "%s : " + " Constant pool is not valid." + " String representation should contain \"%s\" and \"%s\"", testCase.name(), cpClassSimpleName, TEST_CLASS.getName()); throw new AssertionError(msg); } } public static void main(String[] args) { GetConstantPoolTest test = new GetConstantPoolTest(); for (TestCase testCase : TestCase.values()) { test.test(testCase); } testObjectBase(); testMetaspaceWrapperBase(); } private static void testObjectBase() { try { Object cp = CompilerToVMHelper.getConstantPool(new Object(), 0L); throw new AssertionError( "Test OBJECT_BASE." + " Expected IllegalArgumentException has not been caught"); } catch (IllegalArgumentException iae) { // expected } } private static void testMetaspaceWrapperBase() { try { Object cp = CompilerToVMHelper.getConstantPool( new PublicMetaspaceWrapperObject() { @Override public long getMetaspacePointer() { return getPtrToCpAddress(); } }, 0L); throw new AssertionError( "Test METASPACE_WRAPPER_BASE." + " Expected IllegalArgumentException has not been caught"); } catch (IllegalArgumentException iae) { // expected } } private static long getPtrToCpAddress() { Field field; try { field = TEST_CLASS.getDeclaredField("CP_ADDRESS"); } catch (NoSuchFieldException nsfe) { throw new Error("TESTBUG : cannot find field \"CP_ADDRESS\" : " + nsfe.getMessage(), nsfe); } Object base = UNSAFE.staticFieldBase(field); return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field); } }