houzhongjian
2024-11-14 08923c6d95dc8f0f415de94e1d4e3230cdcf7a8e
提交 | 用户 | 时间
912a1e 1 package com.iailab.module.model.mpk.common.utils;
D 2
a8f2f4 3 import cn.hutool.core.io.FileUtil;
1a2b62 4 import com.iail.model.IAILModel;
D 5 import com.iail.utils.RSAUtils;
c12dae 6 import com.iailab.module.model.mpk.common.MdkConstant;
912a1e 7 import lombok.extern.slf4j.Slf4j;
D 8 import org.apache.commons.lang3.StringUtils;
9
10 import java.io.File;
11 import java.lang.reflect.Field;
12 import java.lang.reflect.Method;
13 import java.net.URL;
14 import java.net.URLClassLoader;
c12dae 15 import java.util.HashMap;
912a1e 16 import java.util.Iterator;
D 17 import java.util.Vector;
18
19 @Slf4j
20 public class DllUtils {
c12dae 21
D 22     private static HashMap<String, URLClassLoader> classLoaderCache = new HashMap<>();
912a1e 23
D 24     /**
25      * @description: 加载dll到指定class下
26      * @author: dzd
27      * @date: 2024/9/30 14:27
28      **/
29     public static void loadDll(Class<?> clazz, String dllPath) {
30         try {
c12dae 31             Method method = Runtime.class.getDeclaredMethod("load0", Class.class, String.class);
912a1e 32             boolean accessible = method.isAccessible();
D 33             method.setAccessible(true);
c12dae 34             method.invoke(Runtime.getRuntime(), clazz, dllPath);
912a1e 35             method.setAccessible(accessible);
c12dae 36             log.info("成功加载dll:" + dllPath);
912a1e 37         } catch (Exception e) {
c12dae 38             throw new RuntimeException("加载dll异常", e);
912a1e 39         }
D 40     }
41
42     /**
43      * @description: 卸载classLoader下全部dll
44      * @author: dzd
45      * @date: 2024/9/30 14:31
46      **/
c12dae 47     public static synchronized void unloadDll(URLClassLoader classLoader) {
912a1e 48         try {
D 49             Field field = ClassLoader.class.getDeclaredField("nativeLibraries");
50             field.setAccessible(true);
51             Vector<Object> libs = (Vector<Object>) field.get(classLoader);
52             Iterator<Object> it = libs.iterator();
53             Object o;
54             while (it.hasNext()) {
55                 o = it.next();
56                 Method method = o.getClass().getDeclaredMethod("finalize");
57                 boolean accessible = method.isAccessible();
58                 method.setAccessible(true);
59                 method.invoke(o);
60                 method.setAccessible(accessible);
61
62                 Field nameDield = o.getClass().getDeclaredField("name");
63                 nameDield.setAccessible(true);
64                 String name = (String) nameDield.get(o);
65
66                 log.info("成功卸载dll:" + name);
67             }
68         } catch (Exception e) {
c12dae 69             throw new RuntimeException("卸载dll异常", e);
912a1e 70         }
D 71     }
72
73     /**
74      * @description: 从classLoader中卸载dll,如果dllName传null,则默认删除全部dll
75      * @author: dzd
76      * @date: 2024/9/30 14:52
77      **/
c12dae 78     public static synchronized void unloadDllName(URLClassLoader classLoader, String dllName) {
912a1e 79         try {
D 80             Field field = ClassLoader.class.getDeclaredField("nativeLibraries");
81             field.setAccessible(true);
82             Vector<Object> libs = (Vector<Object>) field.get(classLoader);
83             Iterator<Object> it = libs.iterator();
84             Object o;
85             while (it.hasNext()) {
86                 o = it.next();
87                 Field nameDield = o.getClass().getDeclaredField("name");
88                 nameDield.setAccessible(true);
89                 String name = (String) nameDield.get(o);
90                 // dllName不为null 并且 不等于name,跳出(dllName为null默认全部删除)
91                 if (StringUtils.isNotEmpty(dllName) && !dllName.equals(name)) {
92                     return;
93                 }
94                 Method method = o.getClass().getDeclaredMethod("finalize");
95                 boolean accessible = method.isAccessible();
96                 method.setAccessible(true);
97                 method.invoke(o);
98                 method.setAccessible(accessible);
99                 log.info("成功卸载dll:" + name);
100             }
101         } catch (Exception e) {
c12dae 102             throw new RuntimeException("卸载dll异常", e);
912a1e 103         }
D 104     }
105
106     /**
107      * @description: 加载jar到特定的URLClassLoader,并返回URLClassLoader
108      * @author: dzd
109      * @date: 2024/9/30 14:20
110      **/
111     public static synchronized URLClassLoader loadJar(String jarPath) {
112         File jarFile = new File(jarPath);
113         if (!jarFile.exists()) {
c12dae 114             throw new RuntimeException("jar沒有找到!"+jarPath);
912a1e 115         } else {
D 116             try {
c12dae 117                 // 设置classloader的patent为null,限制使用双亲委派,防止其他classloader找到class,导致dll加载到其他classloader
D 118                 URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()},null,null);
119                 log.info("成功加载jar包:" + jarFile.getAbsolutePath());
912a1e 120                 return urlClassLoader;
D 121             } catch (Exception e) {
c12dae 122                 throw new RuntimeException("加载jar异常", e);
912a1e 123             }
D 124         }
125     }
126
c12dae 127     public static synchronized void unloadJar(URLClassLoader urlClassLoader) {
912a1e 128         try {
D 129             urlClassLoader.close();
130             log.info("成功卸载jar包。");
131         } catch (Exception e) {
c12dae 132             throw new RuntimeException("卸载jar异常", e);
912a1e 133         }
D 134     }
c12dae 135
D 136     public static synchronized void addClassLoaderCache(String projectId, URLClassLoader urlClassLoader) {
137         classLoaderCache.put(projectId, urlClassLoader);
138     }
139
140     public static synchronized URLClassLoader getClassLoader(String projectId) {
141         return classLoaderCache.get(projectId);
142     }
143
144     public static synchronized void removeClassLoaderCache(String projectId) {
145         if (classLoaderCache.containsKey(projectId)) {
146             URLClassLoader urlClassLoader = classLoaderCache.get(projectId);
147             unloadDll(urlClassLoader);
148             unloadJar(urlClassLoader);
149             classLoaderCache.remove(projectId);
150         }
151     }
152
153     public static void removeOldFile(String bakPath,String projectId) {
154         File dir = new File(bakPath);
155         if (dir.exists() && dir.isDirectory()) {
156             File[] files = dir.listFiles();
157             if (null != files && files.length > 0) {
158                 for (File file : files) {
159                     if (file.getName().startsWith(projectId)) {
160                         file.delete();
161                     }
162                 }
163             }
164         }
165     }
166
167     /**
168      * @description: 项目启动加载已发布的dll和jar
169      * @author: dzd
170      * @date: 2024/10/10 11:58
171      **/
172     public static void loadProjectPublish(String bakPath) {
173         File dir = new File(bakPath);
174         if (dir.exists() && dir.isDirectory()) {
175             File[] files = dir.listFiles();
176             if (null != files && files.length > 0) {
177                 for (File file : files) {
178                     String fileName = file.getName();
179                     if (fileName.endsWith(".jar")) {
180                         String[] split = fileName.substring(0,fileName.length() - 4).split(MdkConstant.SPLIT);
181                         String projectId = split[0];
182                         String historyId = split[1];
183
184                         String jarFilePath = bakPath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar";
185                         String dllFilePath = bakPath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll";
186
a8f2f4 187                         if (FileUtil.exist(jarFilePath) && FileUtil.exist(dllFilePath)) {
D 188                             URLClassLoader urlClassLoader = null;
189                             try {
190                                 // 加载新的jar
191                                 urlClassLoader = loadJar(jarFilePath);
192                             } catch (Exception e) {
193                                 throw new RuntimeException("加载jar异常",e);
194                             }
c12dae 195
a8f2f4 196                             try {
D 197                                 // 加载新的dll
198                                 loadDll(urlClassLoader.loadClass("iail.mdk.model.common.Environment"),dllFilePath);
199                             } catch (Exception e) {
200                                 unloadJar(urlClassLoader);
201                                 throw new RuntimeException("加载dll异常",e);
202                             }
203                             // 都加载成功后加入缓存
204                             addClassLoaderCache(projectId,urlClassLoader);
c12dae 205                         }
D 206                     }
207                 }
208             }
209         }
210
211     }
1a2b62 212
D 213     public static HashMap<String, Object> run(IAILModel model, Object[] paramsValueArray, String projectId) throws Exception {
214         if (RSAUtils.checkLisenceBean().getCode() != 1) {
215             throw new SecurityException("Lisence 不可用!");
216         } else if (model == null) {
217             throw new RuntimeException("模型文件不能为空!");
218         } else {
219             URLClassLoader classLoader = DllUtils.getClassLoader(projectId);
a8c6a6 220             if (null == classLoader) {
D 221                 throw new RuntimeException("dll未发布,classLoader为null");
222             }
1a2b62 223             Class<?> clazz = classLoader.loadClass(model.getClassName());
D 224             Method method = clazz.getMethod(model.getMethodName(), model.getParamsArray());
225             return (HashMap)method.invoke(clazz.newInstance(), paramsValueArray);
226         }
227     }
912a1e 228 }