Skip to content
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ static private void makeSureIsCompiled(Method m) {
*/
static public void main(String[] args) throws Exception {
// (1) Load an anonymous version of this class using the corresponding Unsafe method
URL classUrl = TestAnonymousClassUnloading.class.getResource("TestAnonymousClassUnloading.class");
String rn = TestAnonymousClassUnloading.class.getSimpleName() + ".class";
URL classUrl = TestAnonymousClassUnloading.class.getResource(rn);
URLConnection connection = classUrl.openConnection();

int length = connection.getContentLength();
Expand Down
55 changes: 49 additions & 6 deletions hotspot/test/runtime/Metaspace/FragmentMetaspaceSimple.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. 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
Expand All @@ -21,14 +21,19 @@
* questions.
*/

// ClassFileInstaller is needed to place test.Empty into well-known place
/**
* @test
* @library /runtime/testlibrary
* @library classes
* @build test.Empty ClassUnloadCommon
* @library /test/lib classes
* @build test.Empty
* @run driver ClassFileInstaller test.Empty
* @run main/othervm/timeout=200 FragmentMetaspaceSimple
*/

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;

/**
Expand All @@ -47,8 +52,14 @@ public static void main(String... args) {
private static void runSimple(long time) {
long startTime = System.currentTimeMillis();
ArrayList<ClassLoader> cls = new ArrayList<>();
for (int i = 0; System.currentTimeMillis() < startTime + time; ++i) {
ClassLoader ldr = ClassUnloadCommon.newClassLoader();
char sep = File.separatorChar;
String fileName = "test" + sep + "Empty.class";
File file = new File(fileName);
byte buff[] = read(file);

int i = 0;
for (i = 0; System.currentTimeMillis() < startTime + time; ++i) {
ClassLoader ldr = new MyClassLoader(buff);
if (i % 1000 == 0) {
cls.clear();
}
Expand All @@ -59,11 +70,43 @@ private static void runSimple(long time) {
Class<?> c = null;
try {
c = ldr.loadClass("test.Empty");
c.getClass().getClassLoader(); // make sure we have a valid class.
} catch (ClassNotFoundException ex) {
System.out.println("i=" + i + ", len" + buff.length);
throw new RuntimeException(ex);
}
c = null;
}
cls = null;
System.out.println("Finished " + i + " iterations in " +
(System.currentTimeMillis() - startTime) + " ms");
}

private static byte[] read(File file) {
byte buff[] = new byte[(int)(file.length())];
try {
DataInputStream din = new DataInputStream(new FileInputStream(file));
din.readFully(buff);
din.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
return buff;
}

static class MyClassLoader extends ClassLoader {
byte buff[];
MyClassLoader(byte buff[]) {
this.buff = buff;
}

public Class<?> loadClass() throws ClassNotFoundException {
String name = "test.Empty";
try {
return defineClass(name, buff, 0, buff.length);
} catch (Throwable e) {
throw new ClassNotFoundException(name, e);
}
}
}
}
45 changes: 39 additions & 6 deletions hotspot/test/runtime/testlibrary/ClassUnloadCommon.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.stream.Stream;

public class ClassUnloadCommon {
public static class TestFailure extends RuntimeException {
Expand Down Expand Up @@ -55,14 +57,45 @@ public static void triggerUnloading() {
System.gc();
}

/**
* Creates a class loader that loads classes from {@code ${test.class.path}}
* before delegating to the system class loader.
*/
public static ClassLoader newClassLoader() {
String cp = System.getProperty("test.class.path", ".");
URL[] urls = Stream.of(cp.split(File.pathSeparator))
.map(Paths::get)
.map(ClassUnloadCommon::toURL)
.toArray(URL[]::new);
return new URLClassLoader(urls) {
@Override
public Class<?> loadClass(String cn, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(cn)) {
Class<?> c = findLoadedClass(cn);
if (c == null) {
try {
c = findClass(cn);
} catch (ClassNotFoundException e) {
c = getParent().loadClass(cn);
}

}
if (resolve) {
resolveClass(c);
}
return c;
}
}
};
}

static URL toURL(Path path) {
try {
return new URLClassLoader(new URL[] {
Paths.get(System.getProperty("test.classes",".") + File.separatorChar + "classes").toUri().toURL(),
}, null);
} catch (MalformedURLException e){
throw new RuntimeException("Unexpected URL conversion failure", e);
return path.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}

}