From 2b47c5b0e504a653fe40ae8b6749e14e228a89bd Mon Sep 17 00:00:00 2001 From: dongyukun <1208714201@qq.com> Date: 星期四, 02 一月 2025 13:46:57 +0800 Subject: [PATCH] 调度模型下发 --- iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/utils/DllUtils.java | 161 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 146 insertions(+), 15 deletions(-) diff --git a/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/utils/DllUtils.java b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/utils/DllUtils.java index d4831ad..74df6bb 100644 --- a/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/utils/DllUtils.java +++ b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/utils/DllUtils.java @@ -1,19 +1,29 @@ package com.iailab.module.model.mpk.common.utils; +import cn.hutool.core.io.FileUtil; +import com.iail.model.IAILModel; +import com.iail.utils.RSAUtils; +import com.iailab.module.model.mpk.common.MdkConstant; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import sun.misc.URLClassPath; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.HashMap; import java.util.Iterator; import java.util.Vector; +import java.util.stream.Collectors; @Slf4j public class DllUtils { + + private static HashMap<String, URLClassLoader> classLoaderCache = new HashMap<>(); + private static HashMap<String, Object> classCache = new HashMap<>(); + private static HashMap<String, Method> classMethodCache = new HashMap<>(); /** * @description: 加载dll到指定class下 @@ -22,14 +32,14 @@ **/ public static void loadDll(Class<?> clazz, String dllPath) { try { - Method method = Runtime.class.getDeclaredMethod("load0", Class.class,String.class); + Method method = Runtime.class.getDeclaredMethod("load0", Class.class, String.class); boolean accessible = method.isAccessible(); method.setAccessible(true); - method.invoke(Runtime.getRuntime(), clazz,dllPath); + method.invoke(Runtime.getRuntime(), clazz, dllPath); method.setAccessible(accessible); - log.info("成功加载dll:"+ dllPath); + log.info("成功加载dll:" + dllPath); } catch (Exception e) { - throw new RuntimeException("加载dll异常",e); + throw new RuntimeException("加载dll异常", e); } } @@ -38,7 +48,7 @@ * @author: dzd * @date: 2024/9/30 14:31 **/ - public static synchronized void uploadDll(URLClassLoader classLoader) { + public static synchronized void unloadDll(URLClassLoader classLoader) { try { Field field = ClassLoader.class.getDeclaredField("nativeLibraries"); field.setAccessible(true); @@ -60,7 +70,7 @@ log.info("成功卸载dll:" + name); } } catch (Exception e) { - throw new RuntimeException("卸载dll异常",e); + throw new RuntimeException("卸载dll异常", e); } } @@ -69,7 +79,7 @@ * @author: dzd * @date: 2024/9/30 14:52 **/ - public static synchronized void uploadDllName(URLClassLoader classLoader,String dllName) { + public static synchronized void unloadDllName(URLClassLoader classLoader, String dllName) { try { Field field = ClassLoader.class.getDeclaredField("nativeLibraries"); field.setAccessible(true); @@ -93,7 +103,7 @@ log.info("成功卸载dll:" + name); } } catch (Exception e) { - throw new RuntimeException("卸载dll异常",e); + throw new RuntimeException("卸载dll异常", e); } } @@ -105,24 +115,145 @@ public static synchronized URLClassLoader loadJar(String jarPath) { File jarFile = new File(jarPath); if (!jarFile.exists()) { - throw new RuntimeException("jar沒有找到!"); + throw new RuntimeException("jar沒有找到!"+jarPath); } else { try { - URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()}); - log.info("成功加载jar包:"+ jarFile.getAbsolutePath()); + // 设置classloader的patent为null,限制使用双亲委派,防止其他classloader找到class,导致dll加载到其他classloader + URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()},null,null); + log.info("成功加载jar包:" + jarFile.getAbsolutePath()); return urlClassLoader; } catch (Exception e) { - throw new RuntimeException("加载jar异常",e); + throw new RuntimeException("加载jar异常", e); } } } - public static synchronized void uploadJar(URLClassLoader urlClassLoader) { + public static synchronized void unloadJar(URLClassLoader urlClassLoader) { try { urlClassLoader.close(); log.info("成功卸载jar包。"); } catch (Exception e) { - throw new RuntimeException("卸载jar异常",e); + throw new RuntimeException("卸载jar异常", e); + } + } + + public static synchronized void addClassLoaderCache(String projectId, URLClassLoader urlClassLoader) { + classLoaderCache.put(projectId, urlClassLoader); + } + + public static synchronized URLClassLoader getClassLoader(String projectId) { + return classLoaderCache.get(projectId); + } + + public static synchronized void removeClassLoaderCache(String projectId) { + if (classLoaderCache.containsKey(projectId)) { + URLClassLoader urlClassLoader = classLoaderCache.get(projectId); + unloadDll(urlClassLoader); + unloadJar(urlClassLoader); + classLoaderCache.remove(projectId); + removeClassCache(projectId); + removeClassMethodCache(projectId); + } + } + public static synchronized void removeClassCache(String projectId) { + for (String key : classCache.keySet()) { + if (key.startsWith(projectId)) { + classCache.remove(key); + } + } + } + + public static synchronized void removeClassMethodCache(String projectId) { + for (String key : classMethodCache.keySet()) { + if (key.startsWith(projectId)) { + classMethodCache.remove(key); + } + } + } + + public static void removeOldFile(String bakPath,String projectId) { + File dir = new File(bakPath); + if (dir.exists() && dir.isDirectory()) { + File[] files = dir.listFiles(); + if (null != files && files.length > 0) { + for (File file : files) { + if (file.getName().startsWith(projectId)) { + file.delete(); + } + } + } + } + } + + /** + * @description: 项目启动加载已发布的dll和jar + * @author: dzd + * @date: 2024/10/10 11:58 + **/ + public static void loadProjectPublish(String bakPath) { + File dir = new File(bakPath); + if (dir.exists() && dir.isDirectory()) { + File[] files = dir.listFiles(); + if (null != files && files.length > 0) { + for (File file : files) { + String fileName = file.getName(); + if (fileName.endsWith(".jar")) { + String[] split = fileName.substring(0,fileName.length() - 4).split(MdkConstant.SPLIT); + String projectId = split[0]; + String historyId = split[1]; + + String jarFilePath = bakPath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"; + String dllFilePath = bakPath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"; + + if (FileUtil.exist(jarFilePath) && FileUtil.exist(dllFilePath)) { + URLClassLoader urlClassLoader = null; + try { + // 加载新的jar + urlClassLoader = loadJar(jarFilePath); + } catch (Exception e) { + throw new RuntimeException("加载jar异常",e); + } + + try { + // 加载新的dll + loadDll(urlClassLoader.loadClass("iail.mdk.model.common.Environment"),dllFilePath); + } catch (Exception e) { + unloadJar(urlClassLoader); + throw new RuntimeException("加载dll异常",e); + } + // 都加载成功后加入缓存 + addClassLoaderCache(projectId,urlClassLoader); + } + } + } + } + } + + } + + public static HashMap<String, Object> run(IAILModel model, Object[] paramsValueArray, String projectId) throws Exception { + if (RSAUtils.checkLisenceBean().getCode() != 1) { + throw new SecurityException("Lisence 不可用!"); + } else if (model == null) { + throw new RuntimeException("模型文件不能为空!"); + } else { + String classCacheKey = projectId + "_" + model.getClassName(); + String methodParams = Arrays.stream(model.getParamsArray()).map(e -> e.getName()).collect(Collectors.joining(",")); + String classMethodCacheKey = classCacheKey + "." + model.getMethodName() + "(" + methodParams + ")"; + if (classCache.containsKey(classCacheKey) && classMethodCache.containsKey(classMethodCacheKey)) { + return (HashMap)classMethodCache.get(classMethodCacheKey).invoke( classCache.get(classCacheKey), paramsValueArray); + }else { + URLClassLoader classLoader = DllUtils.getClassLoader(projectId); + if (null == classLoader) { + throw new RuntimeException("dll未发布,classLoader为null"); + } + Class<?> clazz = classLoader.loadClass(model.getClassName()); + Object o = clazz.newInstance(); + Method method = clazz.getMethod(model.getMethodName(), model.getParamsArray()); + classCache.put(classCacheKey,o); + classMethodCache.put(classMethodCacheKey,method); + return (HashMap)method.invoke(o, paramsValueArray); + } } } } -- Gitblit v1.9.3