Skip to content

Commit

Permalink
[GR-18955] Fix classloader isolation on JDK 11.
Browse files Browse the repository at this point in the history
PullRequest: graal/4636
  • Loading branch information
chumer committed Oct 19, 2019
2 parents 186cc43 + 9491d62 commit bfc8daa
Show file tree
Hide file tree
Showing 23 changed files with 294 additions and 297 deletions.
17 changes: 3 additions & 14 deletions sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -512,15 +512,7 @@ public Engine build() {

static class APIAccessImpl extends AbstractPolyglotImpl.APIAccess {

private final boolean useContextClassLoader;

APIAccessImpl(boolean useContextClassLoader) {
this.useContextClassLoader = useContextClassLoader;
}

@Override
public boolean useContextClassLoader() {
return useContextClassLoader;
APIAccessImpl() {
}

@Override
Expand Down Expand Up @@ -677,8 +669,6 @@ private static AbstractPolyglotImpl initEngineImpl() {
public AbstractPolyglotImpl run() {
AbstractPolyglotImpl engine = null;
Class<?> servicesClass = null;
boolean useContextClassLoader = false;

if (Boolean.getBoolean("graalvm.ForcePolyglotInvalid")) {
engine = createInvalidPolyglotImpl();
} else {
Expand All @@ -700,15 +690,14 @@ public AbstractPolyglotImpl run() {
}

if (engine == null) {
// >= JDK 9.
engine = searchServiceLoader();
useContextClassLoader = true;
}
if (engine == null) {
engine = createInvalidPolyglotImpl();
}

if (engine != null) {
engine.setConstructors(new APIAccessImpl(useContextClassLoader));
engine.setConstructors(new APIAccessImpl());
}
return engine;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ protected APIAccess() {
}
}

public abstract boolean useContextClassLoader();

public abstract Engine newEngine(AbstractEngineImpl impl);

public abstract Context newContext(AbstractContextImpl impl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.Set;
import java.util.List;

import org.junit.Test;

Expand All @@ -66,7 +66,7 @@ public void loadLanguageByOwnClassLoaderOnJDK8() throws Exception {
return;
}
final URL truffleURL = source.getLocation();
final String locatorName = "com.oracle.truffle.api.impl.TruffleLocator";
final String locatorName = "com.oracle.truffle.polyglot.EngineAccessor";
ClassLoader loader = new URLClassLoader(new URL[]{truffleURL}) {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Expand All @@ -76,12 +76,12 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {
return super.loadClass(name);
}
};
Class<?> locator = loader.loadClass(locatorName);
assertEquals("Right classloader", loader, locator.getClassLoader());
Class<?> locatorClass = loader.loadClass(locatorName);
assertEquals("Right classloader", loader, locatorClass.getClassLoader());

final Method loadersMethod = locator.getDeclaredMethod("loaders");
final Method loadersMethod = locatorClass.getDeclaredMethod("locatorOrDefaultLoaders");
ReflectionUtils.setAccessible(loadersMethod, true);
Set<?> loaders = (Set<?>) loadersMethod.invoke(null);
List<?> loaders = (List<?>) loadersMethod.invoke(null);
assertTrue("Contains locator's loader: " + loaders, loaders.contains(loader));
assertTrue("Contains system loader: " + loader, loaders.contains(ClassLoader.getSystemClassLoader()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
*/
package com.oracle.truffle.api.test.polyglot;

import com.oracle.truffle.api.TruffleLanguage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -52,12 +51,17 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.Assert;
import org.junit.Test;

import com.oracle.truffle.api.TruffleLanguage;

public class LanguageCacheTest {

@Test
Expand All @@ -75,9 +79,9 @@ public void testDuplicateLanguageIds() throws Throwable {
private static Map<String, Object> invokeLanguageCacheCreateLanguages(ClassLoader loader) throws Throwable {
try {
final Class<?> langCacheClz = Class.forName("com.oracle.truffle.polyglot.LanguageCache", true, LanguageCacheTest.class.getClassLoader());
final Method createLanguages = langCacheClz.getDeclaredMethod("createLanguages", ClassLoader.class);
final Method createLanguages = langCacheClz.getDeclaredMethod("createLanguages", List.class);
createLanguages.setAccessible(true);
return (Map<String, Object>) createLanguages.invoke(null, loader);
return (Map<String, Object>) createLanguages.invoke(null, Arrays.asList(LanguageCacheTest.class.getClassLoader(), loader));
} catch (InvocationTargetException ite) {
throw ite.getCause();
} catch (ReflectiveOperationException re) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,13 @@
*/
package com.oracle.truffle.api.test.source;

import java.io.IOException;
import java.nio.charset.Charset;

import com.oracle.truffle.api.TruffleFile;
import com.oracle.truffle.api.TruffleFile.FileTypeDetector;
import com.oracle.truffle.api.impl.TruffleLocator;
import com.oracle.truffle.api.test.polyglot.ProxyLanguage;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import static org.junit.Assert.assertNotNull;
import com.oracle.truffle.api.TruffleFile.FileTypeDetector;
import java.nio.charset.Charset;

public final class CommonMIMETypeLocator extends TruffleLocator {
public static final class Detector implements FileTypeDetector {
Expand All @@ -71,33 +68,6 @@ public Charset findEncoding(TruffleFile file) throws IOException {

@Override
public void locate(Response response) {
response.registerClassLoader(new CommonLoader());
}

private static class CommonLoader extends ClassLoader {
CommonLoader() {
super(getSystemClassLoader());
}

@Override
protected URL findResource(String name) {
if (name.equals("META-INF/truffle/language")) {
return getResource("com/oracle/truffle/api/test/source/CommonMIMETypeLocator");
}
return super.findResource(name);
}

@Override
protected Enumeration<URL> findResources(String name) throws IOException {
if (name.equals("META-INF/truffle/language")) {
URL locator = ClassLoader.getSystemClassLoader().getResource(
"com/oracle/truffle/api/test/source/CommonMIMETypeLocator");
assertNotNull("We have to find a locator registration", locator);
return Collections.enumeration(Collections.singleton(locator));
}
Enumeration<URL> ret = getParent().getResources(name);
return ret;
}
}

public static class LocatorLanguage extends ProxyLanguage {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,6 @@
@SuppressWarnings({"deprecation", "static-method"})
public abstract class Accessor {

@SuppressWarnings("all")
protected final Collection<ClassLoader> loaders() {
return TruffleLocator.loaders();
}

protected void initializeNativeImageTruffleLocator() {
TruffleLocator.initializeNativeImageTruffleLocator();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,15 @@
*/
package com.oracle.truffle.api.impl;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import org.graalvm.nativeimage.ImageInfo;

import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleOptions;
import com.oracle.truffle.api.TruffleRuntime;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicBoolean;
import org.graalvm.nativeimage.ImageInfo;

/**
* Locator that allows the users of the Truffle API to find implementations of languages to be
Expand All @@ -69,29 +68,27 @@ public abstract class TruffleLocator {
*
* @return set of classloaders to search registrations in
*/
public static Set<ClassLoader> loaders() {
Iterable<TruffleLocator> allLocators;
public static List<ClassLoader> loaders() {
TruffleLocator locator = Truffle.getRuntime().getCapability(TruffleLocator.class);
if (locator != null) {
allLocators = Collections.singleton(locator);
List<ClassLoader> found = new ArrayList<>();
Response response = new Response(found);
locator.locate(response);
if (found.isEmpty()) {
// use default
return null;
}
return found;
} else {
allLocators = Collections.emptyList();
}
Set<ClassLoader> found = new LinkedHashSet<>();
Response response = new Response(found);
for (TruffleLocator test : allLocators) {
test.locate(response);
return null;
}
found.add(ClassLoader.getSystemClassLoader());
found.add(TruffleLocator.class.getClassLoader());
return found;
}

static void initializeNativeImageTruffleLocator() {
assert TruffleOptions.AOT : "Only supported in AOT mode.";
if (nativeImageLocator != null) {
if (ImageInfo.inImageBuildtimeCode() || NATIVE_IMAGE_LOCATOR_INITIALIZED.compareAndSet(false, true)) {
nativeImageLocator.locate(new Response(new HashSet<>()));
nativeImageLocator.locate(new Response(new ArrayList<>()));
}
}
}
Expand All @@ -110,9 +107,9 @@ static void initializeNativeImageTruffleLocator() {
* @since 0.18
*/
public static final class Response {
private final Set<ClassLoader> loaders;
private final List<ClassLoader> loaders;

Response(Set<ClassLoader> loaders) {
Response(List<ClassLoader> loaders) {
this.loaders = loaders;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2003,7 +2003,7 @@ public Object get() {

static {
// force loading source accessor
SourceAccessor.allLoaders();
SourceAccessor.load();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.nio.charset.Charset;
import java.util.Set;

import com.oracle.truffle.api.TruffleFile;
import com.oracle.truffle.api.impl.Accessor;
import com.oracle.truffle.api.source.Source.SourceBuilder;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Set;

final class SourceAccessor extends Accessor {

Expand All @@ -58,8 +58,7 @@ final class SourceAccessor extends Accessor {
private SourceAccessor() {
}

static Collection<ClassLoader> allLoaders() {
return ACCESSOR.loaders();
public static void load() {
}

static String getMimeType(TruffleFile file, Set<String> validMimeTypes) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.io.OutputStream;
import java.net.URI;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -75,6 +76,7 @@
import com.oracle.truffle.api.TruffleOptions;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.impl.Accessor;
import com.oracle.truffle.api.impl.TruffleLocator;
import com.oracle.truffle.api.instrumentation.ContextsListener;
import com.oracle.truffle.api.instrumentation.ThreadsListener;
import com.oracle.truffle.api.interop.InteropLibrary;
Expand All @@ -94,8 +96,20 @@ final class EngineAccessor extends Accessor {
static final InstrumentSupport INSTRUMENT = ACCESSOR.instrumentSupport();
static final LanguageSupport LANGUAGE = ACCESSOR.languageSupport();

static Collection<ClassLoader> allLoaders() {
return TruffleOptions.AOT ? Collections.emptyList() : ACCESSOR.loaders();
private static List<ClassLoader> locatorLoaders() {
return TruffleOptions.AOT ? Collections.emptyList() : TruffleLocator.loaders();
}

private static List<ClassLoader> defaultLoaders() {
return Arrays.<ClassLoader> asList(EngineAccessor.class.getClassLoader(), ClassLoader.getSystemClassLoader(), Thread.currentThread().getContextClassLoader());
}

static List<ClassLoader> locatorOrDefaultLoaders() {
List<ClassLoader> loaders = locatorLoaders();
if (loaders == null) {
loaders = defaultLoaders();
}
return loaders;
}

private EngineAccessor() {
Expand Down Expand Up @@ -733,7 +747,7 @@ public Set<String> getValidMimeTypes(String language) {
if (language == null) {
return LanguageCache.languageMimes().keySet();
} else {
LanguageCache lang = LanguageCache.languages(null).get(language);
LanguageCache lang = LanguageCache.languages().get(language);
if (lang != null) {
return lang.getMimeTypes();
} else {
Expand All @@ -744,7 +758,7 @@ public Set<String> getValidMimeTypes(String language) {

@Override
public boolean isCharacterBasedSource(String language, String mimeType) {
LanguageCache cache = LanguageCache.languages(null).get(language);
LanguageCache cache = LanguageCache.languages().get(language);
if (cache == null) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ public PreInitializePath apply(Path path) {

void onPreInitializeContextEnd() {
Map<String, Path> languageHomes = new HashMap<>();
for (LanguageCache cache : LanguageCache.languages(null).values()) {
for (LanguageCache cache : LanguageCache.languages().values()) {
final String languageHome = cache.getLanguageHome();
if (languageHome != null) {
languageHomes.put(cache.getId(), delegate.parsePath(languageHome));
Expand Down Expand Up @@ -390,7 +390,7 @@ private Path getDelegate() {
String path = imageHeapPath.path;
Path result;
String newLanguageHome;
if (languageId != null && (newLanguageHome = LanguageCache.languages(null).get(languageId).getLanguageHome()) != null) {
if (languageId != null && (newLanguageHome = LanguageCache.languages().get(languageId).getLanguageHome()) != null) {
result = delegate.parsePath(newLanguageHome).resolve(path);
} else {
result = delegate.parsePath(path);
Expand Down Expand Up @@ -923,7 +923,7 @@ private Set<Path> getLanguageHomes() {
res = languageHomes;
if (res == null) {
res = new HashSet<>();
for (LanguageCache cache : LanguageCache.languages(null).values()) {
for (LanguageCache cache : LanguageCache.languages().values()) {
final String languageHome = cache.getLanguageHome();
if (languageHome != null) {
res.add(Paths.get(languageHome));
Expand Down
Loading

0 comments on commit bfc8daa

Please sign in to comment.