From a8f2f4e6f1a9173d7eb9779c7879674015c8cda0 Mon Sep 17 00:00:00 2001
From: dengzedong <dengzedong@email>
Date: 星期四, 10 十月 2024 14:07:31 +0800
Subject: [PATCH] 项目启动加载已发布的dll和jar 先判断文件是否存在

---
 iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/utils/DllUtils.java |  112 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 97 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..61cb7a8 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,23 @@
 package com.iailab.module.model.mpk.common.utils;
 
+import cn.hutool.core.io.FileUtil;
+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.HashMap;
 import java.util.Iterator;
 import java.util.Vector;
 
 @Slf4j
 public class DllUtils {
+
+    private static HashMap<String, URLClassLoader> classLoaderCache = new HashMap<>();
 
     /**
      * @description: 加载dll到指定class下
@@ -22,14 +26,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 +42,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 +64,7 @@
                 log.info("成功卸载dll:" + name);
             }
         } catch (Exception e) {
-            throw new RuntimeException("卸载dll异常",e);
+            throw new RuntimeException("卸载dll异常", e);
         }
     }
 
@@ -69,7 +73,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 +97,7 @@
                 log.info("成功卸载dll:" + name);
             }
         } catch (Exception e) {
-            throw new RuntimeException("卸载dll异常",e);
+            throw new RuntimeException("卸载dll异常", e);
         }
     }
 
@@ -105,24 +109,102 @@
     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);
+        }
+    }
+
+    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);
+                        }
+                    }
+                }
+            }
+        }
+
+    }
 }

--
Gitblit v1.9.3