Skip to content

Commit

Permalink
support delegate from classLoaderHook for getResourceAsStream
Browse files Browse the repository at this point in the history
  • Loading branch information
lvjing2 committed Dec 19, 2023
1 parent 52910e5 commit 5bd306b
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.alipay.sofa.ark.container.model.PluginModel;
import com.alipay.sofa.ark.container.service.ArkServiceContainerHolder;
import com.alipay.sofa.ark.exception.ArkLoaderException;
import com.alipay.sofa.ark.exception.ArkRuntimeException;
import com.alipay.sofa.ark.loader.jar.Handler;
import com.alipay.sofa.ark.loader.jar.JarUtils;
import com.alipay.sofa.ark.spi.constant.Constants;
Expand All @@ -32,9 +33,11 @@
import org.apache.commons.io.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
Expand All @@ -48,6 +51,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutionException;
import java.util.jar.JarFile;

Expand All @@ -63,28 +67,40 @@
*/
public abstract class AbstractClasspathClassLoader extends URLClassLoader {

protected static final String CLASS_RESOURCE_SUFFIX = ".class";
protected static final String CLASS_RESOURCE_SUFFIX = ".class";

protected ClassLoaderService classloaderService = ArkServiceContainerHolder
.getContainer()
.getService(
ClassLoaderService.class);
protected ClassLoaderService classloaderService = ArkServiceContainerHolder
.getContainer()
.getService(
ClassLoaderService.class);

protected Cache<String, LoadClassResult> classCache;
protected Cache<String, LoadClassResult> classCache;

protected Cache<String, Optional<Package>> packageCache;
protected Cache<String, Optional<Package>> packageCache;

protected Cache<String, Optional<URL>> urlResourceCache = newBuilder()
.expireAfterWrite(10,
SECONDS).build();
protected boolean exploded = false;
protected Cache<String, Optional<URL>> urlResourceCache = newBuilder()
.expireAfterWrite(10,
SECONDS).build();
protected boolean exploded = false;

protected final WeakHashMap<Closeable, Void> closeables;

static {
ClassLoader.registerAsParallelCapable();
}

public AbstractClasspathClassLoader(URL[] urls) {
super(urls, null);

try {
Field field = URLClassLoader.class.getDeclaredField("closeables");
field.setAccessible(true);
closeables = (WeakHashMap<Closeable, Void>) field.get(this);
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
throw new ArkRuntimeException(String.format(
"[Ark Runtime] Failed to init ClassLoader: %s", this), e.getCause());

Check warning on line 101 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L99-L101

Added lines #L99 - L101 were not covered by tests
}

classCache = newBuilder()
.initialCapacity(
ArkConfigs.getIntValue(Constants.ARK_CLASSLOADER_CACHE_CLASS_SIZE_INITIAL, 2500))
Expand Down Expand Up @@ -265,6 +281,42 @@ public URL getResource(String name) {
}
}

/**
* override the implementation from base URLClassLoader to use getResource in this AbstractClasspathClassLoader
* this method should exactly same with the implementation in base URLClassLoader
* @param name The resource name
*
* @return
*/
@Override
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);

Check warning on line 293 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L293

Added line #L293 was not covered by tests
try {
if (url == null) {
return null;

Check warning on line 296 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L296

Added line #L296 was not covered by tests
}
URLConnection urlc = url.openConnection();
InputStream is = urlc.getInputStream();

Check warning on line 299 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L298-L299

Added lines #L298 - L299 were not covered by tests

if (urlc instanceof JarURLConnection) {
JarURLConnection juc = (JarURLConnection) urlc;
JarFile jar = juc.getJarFile();
synchronized (closeables) {

Check warning on line 304 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L302-L304

Added lines #L302 - L304 were not covered by tests
if (!closeables.containsKey(jar)) {
closeables.put(jar, null);

Check warning on line 306 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L306

Added line #L306 was not covered by tests
}
}

Check warning on line 308 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L308

Added line #L308 was not covered by tests
} else if (urlc instanceof sun.net.www.protocol.file.FileURLConnection) {
synchronized (closeables) {
closeables.put(is, null);
}

Check warning on line 312 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L310-L312

Added lines #L310 - L312 were not covered by tests
}
return is;
} catch (IOException e) {
return null;

Check warning on line 316 in sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java

View check run for this annotation

Codecov / codecov/patch

sofa-ark-parent/core-impl/container/src/main/java/com/alipay/sofa/ark/container/service/classloader/AbstractClasspathClassLoader.java#L314-L316

Added lines #L314 - L316 were not covered by tests
}
}

/**
* Real logic to get resource
* @param name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public Class<?> preFindClass(String name, ClassLoaderService classLoaderService,
@Override
public Class<?> postFindClass(String name, ClassLoaderService classLoaderService, Biz biz)
throws ClassNotFoundException {
ClassLoader bizClassLoader = ArkClient.getMasterBiz().getBizClassLoader();
if (biz == null || (biz.getBizClassLoader() == bizClassLoader)) {
ClassLoader masterClassLoader = ArkClient.getMasterBiz().getBizClassLoader();
if (biz == null || (biz.getBizClassLoader() == masterClassLoader)) {
return null;
}
// The cglib proxy class cannot be delegate to the master, it must be created by the biz's own defineClass
Expand All @@ -60,15 +60,15 @@ public Class<?> postFindClass(String name, ClassLoaderService classLoaderService
return null;
}
// if Master Biz contains same class in multi jar, need to check each whether is provided
Class<?> clazz = bizClassLoader.loadClass(name);
Class<?> clazz = masterClassLoader.loadClass(name);
if (clazz != null) {
if (biz.isDeclared(clazz.getProtectionDomain().getCodeSource().getLocation(), "")) {
return clazz;
}

try {
String classResourceName = name.replace('.', '/') + ".class";
Enumeration<URL> urls = bizClassLoader.getResources(classResourceName);
Enumeration<URL> urls = masterClassLoader.getResources(classResourceName);
while (urls.hasMoreElements()) {
URL resourceUrl = urls.nextElement();
if (resourceUrl != null && biz.isDeclared(resourceUrl, classResourceName)) {
Expand Down Expand Up @@ -97,12 +97,12 @@ public URL postFindResource(String name, ClassLoaderService classLoaderService,
return null;
}

ClassLoader bizClassLoader = ArkClient.getMasterBiz().getBizClassLoader();
if (biz.getBizClassLoader() == bizClassLoader) {
ClassLoader masterClassLoader = ArkClient.getMasterBiz().getBizClassLoader();
if (biz.getBizClassLoader() == masterClassLoader) {
return null;
}
try {
URL resourceUrl = bizClassLoader.getResource(name);
URL resourceUrl = masterClassLoader.getResource(name);
if (resourceUrl != null && biz.isDeclared(resourceUrl, name)) {
return resourceUrl;
}
Expand All @@ -124,12 +124,12 @@ public Enumeration<URL> postFindResources(String name, ClassLoaderService classL
if (biz == null || (!biz.isDeclaredMode() && shouldSkip(name))) {
return null;
}
ClassLoader bizClassLoader = ArkClient.getMasterBiz().getBizClassLoader();
if (biz.getBizClassLoader() == bizClassLoader) {
ClassLoader masterClassLoader = ArkClient.getMasterBiz().getBizClassLoader();
if (biz.getBizClassLoader() == masterClassLoader) {
return null;
}
try {
Enumeration<URL> resourceUrls = bizClassLoader.getResources(name);
Enumeration<URL> resourceUrls = masterClassLoader.getResources(name);
List<URL> matchedResourceUrls = new ArrayList<>();
while (resourceUrls.hasMoreElements()) {
URL resourceUrl = resourceUrls.nextElement();
Expand Down

0 comments on commit 5bd306b

Please sign in to comment.