优化ClassFilter

This commit is contained in:
redkale
2024-02-03 09:50:36 +08:00
parent cd059c02a2
commit dc57d62f34
6 changed files with 91 additions and 75 deletions

View File

@@ -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<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys();
for (FilterEntry<NodeServer> entry : entrys) {
final Class<? extends NodeServer> 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<ModuleEngine> 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);
}

View File

@@ -160,7 +160,7 @@ public final class ClassFilter<T> {
* @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<T> {
* @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<T> {
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<T> {
protected static final Logger logger = Logger.getLogger(Loader.class.getName());
protected static final ConcurrentMap<URL, Set<String>> cache = new ConcurrentHashMap<>();
protected static final ConcurrentMap<URI, Set<String>> cache = new ConcurrentHashMap<>();
private Loader() {
//do nothng
}
public static void close() {
cache.clear();
@@ -575,11 +581,11 @@ public final class ClassFilter<T> {
* @throws IOException 异常
*/
public static void load(final File excludeFile, RedkaleClassLoader loader, final ClassFilter... filters) throws IOException {
List<URL> urlFiles = new ArrayList<>(2);
List<URL> 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<URI> urlFiles = new ArrayList<>(2);
List<URI> 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<T> {
List<File> files = new ArrayList<>();
boolean debug = logger.isLoggable(Level.FINEST);
StringBuilder debugstr = new StringBuilder();
for (final URL url : urlJares) {
for (final URI url : urlJares) {
Set<String> 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<JarEntry> it = jar.entries();
while (it.hasMoreElements()) {
String entryName = it.nextElement().getName().replace('/', '.');
@@ -632,6 +638,18 @@ public final class ClassFilter<T> {
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<T> {
}
}
}
for (final URL url : urlFiles) {
for (final URI url : urlFiles) {
Set<String> classes = cache.get(url);
if (classes == null) {
classes = new LinkedHashSet<>();
final Set<String> 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) {

View File

@@ -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之前

View File

@@ -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();

View File

@@ -401,7 +401,7 @@ public class MessageModuleEngine extends ModuleEngine {
}
try {
ClassFilter.Loader.load(application.getHome(), application.getServerClassLoader(), filter);
application.loadServerClassFilters(filter);
List<ClassFilter.FilterEntry<? extends MessageConsumer>> entrys = new ArrayList(filter.getFilterEntrys());
for (ClassFilter.FilterEntry<? extends MessageConsumer> en : entrys) {
Class<? extends MessageConsumer> clazz = en.getType();

View File

@@ -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<URL> set = new HashSet<>();
HashSet<URI> 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