io.vertx.core.impl.LoaderManager Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.core.impl;
import io.vertx.core.DeploymentOptions;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Supports isolated classloader for Java 8.
*
* For Java 11 and above, the JVM uses a no-op implementation thanks to Multi-Release Jar.
*/
class LoaderManager {
private final Map classLoaders = new HashMap<>();
/**
* IMPORTANT - Isolation groups are not supported on Java 9+ because the application classloader is not
* an URLClassLoader anymore. Thus we can't extract the list of jars to configure the IsolatedClassLoader.
*/
ClassLoaderHolder getClassLoader(DeploymentOptions options) {
String isolationGroup = options.getIsolationGroup();
ClassLoaderHolder holder;
if (isolationGroup == null) {
return null;
} else {
// IMPORTANT - Isolation groups are not supported on Java 9+, because the system classloader is not an URLClassLoader
// anymore. Thus we can't extract the paths from the classpath and isolate the loading.
synchronized (this) {
holder = classLoaders.get(isolationGroup);
if (holder == null) {
ClassLoader current = VerticleManager.getCurrentClassLoader();
if (!(current instanceof URLClassLoader)) {
throw new IllegalStateException("Current classloader must be URLClassLoader");
}
holder = new ClassLoaderHolder(isolationGroup, LoaderManager.buildLoader((URLClassLoader) current, options));
classLoaders.put(isolationGroup, holder);
}
holder.refCount++;
}
}
return holder;
}
void release(ClassLoaderHolder holder) {
synchronized (this) {
if (--holder.refCount == 0) {
classLoaders.remove(holder.group);
if (holder.loader instanceof Closeable) {
try {
((Closeable)holder.loader).close();
} catch (IOException e) {
// log.debug("Issue when closing isolation group loader", e);
}
}
}
}
}
private static ClassLoader buildLoader(URLClassLoader parent, DeploymentOptions options) {
List urls = new ArrayList<>();
// Add any extra URLs to the beginning of the classpath
List extraClasspath = options.getExtraClasspath();
if (extraClasspath != null) {
for (String pathElement: extraClasspath) {
File file = new File(pathElement);
try {
URL url = file.toURI().toURL();
urls.add(url);
} catch (MalformedURLException e) {
throw new IllegalStateException(e);
}
}
}
// And add the URLs of the Vert.x classloader
urls.addAll(Arrays.asList(parent.getURLs()));
return new IsolatingClassLoader(urls.toArray(new URL[0]), parent,
options.getIsolatedClasses());
}
}