From dc57d62f3454ad1681bdb562d1a75edc89addbea Mon Sep 17 00:00:00 2001 From: redkale Date: Sat, 3 Feb 2024 09:50:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96ClassFilter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/redkale/boot/Application.java | 14 ++- .../java/org/redkale/boot/ClassFilter.java | 48 ++++++--- .../java/org/redkale/boot/NodeServer.java | 2 +- .../org/redkale/boot/PrepareCompiler.java | 2 +- .../redkale/mq/spi/MessageModuleEngine.java | 2 +- .../org/redkale/util/RedkaleClassLoader.java | 98 +++++++++---------- 6 files changed, 91 insertions(+), 75 deletions(-) diff --git a/src/main/java/org/redkale/boot/Application.java b/src/main/java/org/redkale/boot/Application.java index 78f834a65..0fba164ac 100644 --- a/src/main/java/org/redkale/boot/Application.java +++ b/src/main/java/org/redkale/boot/Application.java @@ -1317,7 +1317,7 @@ public final class Application { try { if (!inited.getAndSet(true)) { //加载自定义的协议,如:SOCKS ClassFilter profilter = new ClassFilter(classLoader, NodeProtocol.class, NodeServer.class, (Class[]) null); - ClassFilter.Loader.load(home, classLoader, profilter); + loadClassByFilters(profilter); final Set> entrys = profilter.getFilterEntrys(); for (FilterEntry entry : entrys) { final Class type = entry.getType(); @@ -1408,14 +1408,18 @@ public final class Application { }); } - void loadClassesByFilters(final ClassFilter... filters) throws IOException { - ClassFilter.Loader.load(getHome(), this.serverClassLoader, filters); - } - List getModuleEngines() { return moduleEngines; } + public void loadClassByFilters(final ClassFilter... filters) throws IOException { + ClassFilter.Loader.load(getHome(), getClassLoader(), filters); + } + + public void loadServerClassFilters(final ClassFilter... filters) throws IOException { + ClassFilter.Loader.load(getHome(), getServerClassLoader(), filters); + } + public DataSource loadDataSource(final String sourceName, boolean autoMemory) { return sourceModule.loadDataSource(sourceName, autoMemory); } diff --git a/src/main/java/org/redkale/boot/ClassFilter.java b/src/main/java/org/redkale/boot/ClassFilter.java index 2313578f9..3a81c6857 100644 --- a/src/main/java/org/redkale/boot/ClassFilter.java +++ b/src/main/java/org/redkale/boot/ClassFilter.java @@ -160,7 +160,7 @@ public final class ClassFilter { * @param url URL */ @SuppressWarnings("unchecked") - public final void filter(AnyValue property, String clazzName, URL url) { + public final void filter(AnyValue property, String clazzName, URI url) { filter(property, clazzName, true, url); } @@ -183,7 +183,7 @@ public final class ClassFilter { * @param autoScan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略 * @param url URL */ - public final void filter(AnyValue property, String clazzName, boolean autoScan, URL url) { + public final void filter(AnyValue property, String clazzName, boolean autoScan, URI url) { boolean r = accept0(property, clazzName); ClassFilter cf = r ? this : null; if (r && ands != null) { @@ -242,8 +242,10 @@ public final class ClassFilter { return; } } - //&& (!(cfe instanceof NoClassDefFoundError) || (cfe instanceof UnsupportedClassVersionError) || ((NoClassDefFoundError) cfe).getMessage().startsWith("java.lang.NoClassDefFoundError: java"))) { - logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error for class: " + clazzName + (url == null ? "" : (" in " + url)), cfe); + //&& (!(cfe instanceof NoClassDefFoundError) || (cfe instanceof UnsupportedClassVersionError) + //|| ((NoClassDefFoundError) cfe).getMessage().startsWith("java.lang.NoClassDefFoundError: java"))) { + logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + + " filter error for class: " + clazzName + (url == null ? "" : (" in " + url)), cfe); } } } @@ -559,7 +561,11 @@ public final class ClassFilter { protected static final Logger logger = Logger.getLogger(Loader.class.getName()); - protected static final ConcurrentMap> cache = new ConcurrentHashMap<>(); + protected static final ConcurrentMap> cache = new ConcurrentHashMap<>(); + + private Loader() { + //do nothng + } public static void close() { cache.clear(); @@ -575,11 +581,11 @@ public final class ClassFilter { * @throws IOException 异常 */ public static void load(final File excludeFile, RedkaleClassLoader loader, final ClassFilter... filters) throws IOException { - List urlFiles = new ArrayList<>(2); - List urlJares = new ArrayList<>(2); - final URL exurl = excludeFile != null ? excludeFile.toURI().toURL() : null; - for (URL url : loader.getAllURLs()) { - if (exurl != null && exurl.sameFile(url)) { + List urlFiles = new ArrayList<>(2); + List urlJares = new ArrayList<>(2); + final URI exurl = excludeFile != null ? excludeFile.toURI() : null; + for (URI url : loader.getAllURIs()) { + if (exurl != null && exurl.equals(url)) { continue; } if (url.getPath().endsWith(".jar")) { @@ -591,11 +597,11 @@ public final class ClassFilter { List files = new ArrayList<>(); boolean debug = logger.isLoggable(Level.FINEST); StringBuilder debugstr = new StringBuilder(); - for (final URL url : urlJares) { + for (final URI url : urlJares) { Set classes = cache.get(url); if (classes == null) { classes = new LinkedHashSet<>(); - try (JarFile jar = new JarFile(URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8))) { + try (JarFile jar = new JarFile(URLDecoder.decode(url.toURL().getFile(), StandardCharsets.UTF_8))) { Enumeration it = jar.entries(); while (it.hasMoreElements()) { String entryName = it.nextElement().getName().replace('/', '.'); @@ -632,6 +638,18 @@ public final class ClassFilter { if (className.startsWith("org.apache.")) { break; } + if (className.startsWith("org.redisson.")) { + break; + } + if (className.startsWith("com.fasterxml.")) { + break; + } + if (className.startsWith("org.yaml.")) { + break; + } + if (className.startsWith("reactor.")) { + break; + } if (className.startsWith("io.netty.")) { break; } @@ -661,17 +679,17 @@ public final class ClassFilter { } } } - for (final URL url : urlFiles) { + for (final URI url : urlFiles) { Set classes = cache.get(url); if (classes == null) { classes = new LinkedHashSet<>(); final Set cs = classes; - if (url == RedkaleClassLoader.URL_NONE) { + if (url == RedkaleClassLoader.URI_NONE) { loader.forEachCacheClass(v -> cs.add(v)); } if (cs.isEmpty()) { files.clear(); - File root = new File(url.getFile()); + File root = new File(url.toURL().getFile()); String rootPath = root.getPath(); loadClassFiles(excludeFile, root, files); for (File f : files) { diff --git a/src/main/java/org/redkale/boot/NodeServer.java b/src/main/java/org/redkale/boot/NodeServer.java index e3161ac32..b3f36655a 100644 --- a/src/main/java/org/redkale/boot/NodeServer.java +++ b/src/main/java/org/redkale/boot/NodeServer.java @@ -226,7 +226,7 @@ public abstract class NodeServer { filters.addAll(otherFilters); } long s = System.currentTimeMillis(); - application.loadClassesByFilters(filters.toArray(new ClassFilter[filters.size()])); + application.loadClassByFilters(filters.toArray(new ClassFilter[filters.size()])); long e = System.currentTimeMillis() - s; logger.info(this.getClass().getSimpleName() + " load filter class in " + e + " ms"); loadService(serviceFilter); //必须在servlet之前 diff --git a/src/main/java/org/redkale/boot/PrepareCompiler.java b/src/main/java/org/redkale/boot/PrepareCompiler.java index bcee87981..170ed4593 100644 --- a/src/main/java/org/redkale/boot/PrepareCompiler.java +++ b/src/main/java/org/redkale/boot/PrepareCompiler.java @@ -42,7 +42,7 @@ public class PrepareCompiler { final ClassFilter beanFilter2 = new ClassFilter(application.getClassLoader(), org.redkale.util.Bean.class, Object.class, (Class[]) null); final ClassFilter filterFilter = new ClassFilter(application.getClassLoader(), null, FilterBean.class, (Class[]) null); - ClassFilter.Loader.load(application.getHome(), application.getClassLoader(), entityFilter, beanFilter, filterFilter); + application.loadClassByFilters(entityFilter, beanFilter, filterFilter); for (FilterEntry en : entityFilter.getFilterEntrys()) { Class clz = en.getType(); diff --git a/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java b/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java index fd39ed1d9..a46199072 100644 --- a/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java +++ b/src/main/java/org/redkale/mq/spi/MessageModuleEngine.java @@ -401,7 +401,7 @@ public class MessageModuleEngine extends ModuleEngine { } try { - ClassFilter.Loader.load(application.getHome(), application.getServerClassLoader(), filter); + application.loadServerClassFilters(filter); List> entrys = new ArrayList(filter.getFilterEntrys()); for (ClassFilter.FilterEntry en : entrys) { Class clazz = en.getType(); diff --git a/src/main/java/org/redkale/util/RedkaleClassLoader.java b/src/main/java/org/redkale/util/RedkaleClassLoader.java index f7665ad6e..b1705a578 100644 --- a/src/main/java/org/redkale/util/RedkaleClassLoader.java +++ b/src/main/java/org/redkale/util/RedkaleClassLoader.java @@ -27,17 +27,7 @@ public class RedkaleClassLoader extends URLClassLoader { public static final String RESOURCE_CACHE_CONF_PATH = "/META-INF/redkale/conf"; - public static final URL URL_NONE; - - static { - URL url = null; - try { - url = URI.create("file://redkale/uri").toURL(); //不能是jar结尾,否则会视为jar文件url - } catch (MalformedURLException e) { - //do nothing - } - URL_NONE = url; - } + public static final URI URI_NONE = URI.create("file://redkale/uri"); //不能是jar结尾,否则会视为jar文件url private static final String[] buildClasses = {}; @@ -487,60 +477,64 @@ public class RedkaleClassLoader extends URLClassLoader { return super.getURLs(); } - public URL[] getAllURLs() { + public URI[] getAllURIs() { ClassLoader loader = this; - HashSet set = new HashSet<>(); + HashSet set = new HashSet<>(); String appPath = System.getProperty("java.class.path"); if (appPath != null && !appPath.isEmpty()) { for (String path : appPath.replace("://", "&&").replace(":\\", "##").replace(':', ';').split(";")) { try { - set.add(Paths.get(path.replace("&&", "://").replace("##", ":\\")).toRealPath().toFile().toURI().toURL()); + set.add(Paths.get(path.replace("&&", "://").replace("##", ":\\")).toRealPath().toFile().toURI()); } catch (Exception e) { //do nothing } } } - do { - String loaderName = loader.getClass().getName(); - if (loaderName.startsWith("sun.") && loaderName.contains("ExtClassLoader")) { - continue; - } - if (loader instanceof URLClassLoader) { - for (URL url : ((URLClassLoader) loader).getURLs()) { - set.add(url); + try { + do { + String loaderName = loader.getClass().getName(); + if (loaderName.startsWith("sun.") && loaderName.contains("ExtClassLoader")) { + continue; } - } else { //可能JDK9及以上 - loader.getResource("org.redkale"); //必须要运行一次,确保URLClassPath的值被填充完毕 - Class loaderClazz = loader.getClass(); - Object ucp = null; - do { //读取 java.base/jdk.internal.loader.BuiltinClassLoader的URLClassPath ucp值 - try { - //需要在命令行里加入: --add-opens java.base/jdk.internal.loader=ALL-UNNAMED - Field field = loaderClazz.getDeclaredField("ucp"); - field.setAccessible(true); - ucp = field.get(loader); - break; - } catch (Throwable e) { - //do nothing + if (loader instanceof URLClassLoader) { + for (URL url : ((URLClassLoader) loader).getURLs()) { + set.add(url.toURI()); } - } while ((loaderClazz = loaderClazz.getSuperclass()) != Object.class); - if (ucp != null) { //URLClassPath - URL[] urls = null; - try { //读取 java.base/jdk.internal.loader.URLClassPath的urls值 - Method method = ucp.getClass().getMethod("getURLs"); - urls = (URL[]) method.invoke(ucp); - } catch (Exception e) { - //do nothing - } - if (urls != null) { - for (URL url : urls) { - set.add(url); + } else { //可能JDK9及以上 + loader.getResource("org.redkale"); //必须要运行一次,确保URLClassPath的值被填充完毕 + Class loaderClazz = loader.getClass(); + Object ucp = null; + do { //读取 java.base/jdk.internal.loader.BuiltinClassLoader的URLClassPath ucp值 + try { + //需要在命令行里加入: --add-opens java.base/jdk.internal.loader=ALL-UNNAMED + Field field = loaderClazz.getDeclaredField("ucp"); + field.setAccessible(true); + ucp = field.get(loader); + break; + } catch (Throwable e) { + //do nothing + } + } while ((loaderClazz = loaderClazz.getSuperclass()) != Object.class); + if (ucp != null) { //URLClassPath + URL[] urls = null; + try { //读取 java.base/jdk.internal.loader.URLClassPath的urls值 + Method method = ucp.getClass().getMethod("getURLs"); + urls = (URL[]) method.invoke(ucp); + } catch (Exception e) { + //do nothing + } + if (urls != null) { + for (URL url : urls) { + set.add(url.toURI()); + } } } } - } - } while ((loader = loader.getParent()) != null); - return set.toArray(new URL[set.size()]); + } while ((loader = loader.getParent()) != null); + } catch (URISyntaxException e) { + throw new RedkaleException(e); + } + return set.toArray(new URI[set.size()]); } public static class RedkaleCacheClassLoader extends RedkaleClassLoader { @@ -553,8 +547,8 @@ public class RedkaleClassLoader extends URLClassLoader { } @Override - public URL[] getAllURLs() { - return new URL[]{URL_NONE}; + public URI[] getAllURIs() { + return new URI[]{URI_NONE}; } @Override