From 1d27b02e10eda1e47df77862006dfff2dd077854 Mon Sep 17 00:00:00 2001 From: liyongfei Date: Thu, 26 Sep 2024 14:37:38 +0800 Subject: [PATCH] fix:Optimize NativeLoader to Prevent Duplicate Loading and Handle Exceptions --- src/main/java/org/gmssl/NativeLoader.java | 120 +++++++++++++--------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/src/main/java/org/gmssl/NativeLoader.java b/src/main/java/org/gmssl/NativeLoader.java index dc119b8..16e8a44 100644 --- a/src/main/java/org/gmssl/NativeLoader.java +++ b/src/main/java/org/gmssl/NativeLoader.java @@ -11,7 +11,10 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.Properties; @@ -26,7 +29,9 @@ public class NativeLoader { /* custom jni library prefix path relative to project resources */ private static final String RESOURCELIB_PREFIXPATH = "lib"; - static final String GMSSLJNILIB_NAME="libgmssljni"; + static final String GMSSLJNILIB_NAME = "libgmssljni"; + + private static final Map loadedLibraries = new HashMap<>(); private static final Properties PROPERTIES = new Properties(); @@ -44,64 +49,80 @@ public class NativeLoader { /** * load jni lib from resources path,the parameter does not contain the path and suffix. - * @param libaray libarayName * + * @param library libraryName */ - public synchronized static void load (String libaray){ - String resourceLibPath = RESOURCELIB_PREFIXPATH + "/" + libaray + "." + libExtension(); + public static void load(String library) { + if (loadedLibraries.containsKey(library)) { + return; + } + Path tempFile = null; + String resourceLibPath = Paths.get(RESOURCELIB_PREFIXPATH, library + "." + libExtension()).toString(); try (InputStream inputStream = NativeLoader.class.getClassLoader().getResourceAsStream(resourceLibPath)) { - if (null == inputStream) { - throw new GmSSLException("lib file not found in JAR: " + resourceLibPath); - } - Path tempFile = Files.createTempFile(libaray, "."+libExtension()); + tempFile = Files.createTempFile(library, "." + libExtension()); tempFile.toFile().deleteOnExit(); Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING); checkReferencedLib(); System.load(tempFile.toAbsolutePath().toString()); + loadedLibraries.put(library, tempFile); + }catch (IOException e){ + throw new GmSSLException("lib file not found:"+ e.getMessage()); + }catch (UnsatisfiedLinkError e){ + throw new GmSSLException("Failed to load native library:"+ e.getMessage()); } catch (Exception e) { - throw new GmSSLException("Unable to load lib from JAR"); + throw new GmSSLException("Unable to load lib!"); + }finally { + if (null != tempFile) { + tempFile.toFile().delete(); + } } } /** * Get the operating system type. + * * @return operating system name */ - static String osType(){ - String os="unknown"; - String osName = System.getProperty("os.name").toLowerCase(); - if(osName.startsWith("windows")){ - os="win"; - } - if(osName.startsWith("linux")){ - if ("dalvik".equalsIgnoreCase(System.getProperty("java.vm.name"))) { - os = "android"; - System.setProperty("jna.nounpack", "true"); - } else { - os="linux"; - } + static String osType() { + String os = "unknown"; + String vmName = System.getProperty("java.vm.name"); + if ("dalvik".equalsIgnoreCase(vmName) || "art".equalsIgnoreCase(vmName)) { + os = "android"; } - if(osName.startsWith("mac os x") || osName.startsWith("darwin")){ - os="osx"; + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.startsWith("windows")) { + os = "win"; + } else if (osName.startsWith("linux")) { + os = "linux"; + } else if (osName.startsWith("mac os x") || osName.startsWith("darwin")) { + os = "osx"; + } else { + System.err.println("Unsupported OS: " + osName); } return os; } /** * Get the library extension name based on the operating system type. + * * @return extension name */ - static String libExtension(){ - String osType=osType(); - String libExtension=null; - if("win".equals(osType)){ - libExtension="dll"; - } - if("osx".equals(osType)){ - libExtension="dylib"; - } - if("linux".equals(osType)){ - libExtension="so"; + static String libExtension() { + String osType = osType(); + String libExtension = null; + switch (osType) { + case "win": + libExtension = "dll"; + break; + case "osx": + libExtension = "dylib"; + break; + case "linux": + case "android": + libExtension = "so"; + break; + default: + throw new IllegalArgumentException("Unsupported OS type!"); } return libExtension; } @@ -112,20 +133,21 @@ static String libExtension(){ * in order to correct the @rpath path issue. Alternatively, you can manually execute the command * "install_name_tool -change @rpath/libgmssl.3.dylib /usr/local/lib/libgmssl.3.dylib xxx/lib/libgmssljni.dylib" to fix the library reference path issue. * This has already been loaded and manual execution is unnecessary. - * */ - private static void checkReferencedLib(){ - if("osx".equals(osType())){ - String macReferencedLib=PROPERTIES.getProperty("macReferencedLib"); - Optional optionalStr = Optional.ofNullable(macReferencedLib); - if(optionalStr.isPresent() && !optionalStr.get().isEmpty()){ - File libFile = new File(macReferencedLib); - if(libFile.exists()){ - System.load(macReferencedLib); - } - } - - } - } + private static void checkReferencedLib() { + if ("osx".equals(osType())) { + String macReferencedLib = PROPERTIES.getProperty("macReferencedLib"); + if (null != macReferencedLib) { + System.load(macReferencedLib); + Optional optionalStr = Optional.ofNullable(macReferencedLib); + if (optionalStr.isPresent() && !optionalStr.get().isEmpty()) { + File libFile = new File(macReferencedLib); + if (libFile.exists()) { + System.load(macReferencedLib); + } + } + } + } + } }