zoukankan      html  css  js  c++  java
  • 加载rocksdb实例报错:java.lang.UnsatisfiedLinkError: C:UsersAdministratorAppDataLocalTemplibrocksdbjni3696928169151614297.dll

      项目的缓存中用到了rocksdb,实例化时报错了:

    Related cause:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.beans.factory.config.MethodInvokingFactoryBean#1' defined in class path resource [spring-core.xml]: Cannot resolve reference to bean 'milletContext' while setting bean property 'arguments' with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'milletContext' defined in class path resource [spring-core.xml]: Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: C:UsersAdministratorAppDataLocalTemplibrocksdbjni3696928169151614297.dll: �
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:382)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1531)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1276)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getTypeForFactoryBean(AbstractBeanFactory.java:1508)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:816)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:558)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:432)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:403)
    at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:220)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1267)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1101)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4745)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5207)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:752)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1144)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1878)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'milletContext' defined in class path resource [spring-core.xml]: Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: C:UsersAdministratorAppDataLocalTemplibrocksdbjni3696928169151614297.dll: �
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
    ... 48 more
    Caused by: java.lang.UnsatisfiedLinkError: C:UsersAdministratorAppDataLocalTemplibrocksdbjni3696928169151614297.dll: �
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
    at java.lang.Runtime.load0(Runtime.java:809)
    at java.lang.System.load(System.java:1086)
    at org.rocksdb.NativeLibraryLoader.loadLibraryFromJar(NativeLibraryLoader.java:78)
    at org.rocksdb.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:56)
    at org.rocksdb.RocksDB.loadLibrary(RocksDB.java:64)
    at org.rocksdb.RocksDB.<clinit>(RocksDB.java:35)
    at org.rocksdb.Options.<clinit>(Options.java:25)
    at cn.migu.millet.common.CacheStorage.open(CacheStorage.java:31)
    at cn.migu.millet.MilletContext.init(MilletContext.java:169)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1758)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1695)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
    ... 55 more

      问题现象:类加载失败引起的一系列后续问题:类找不到、实例加载失败、容器加载失败。

      问题定位:代码跟踪

      public static CacheStorage open(String path) {
        try (final Options options = new Options()) {
          options.setCreateIfMissing(true);
          try {
            return new CacheStorage(RocksDB.open(options, path));
          } catch (RocksDBException e) {
            logger.error("open cache db error, path={}, e={}", path, e.getMessage());
            return null;
          }
        }
      }
    public class Options extends RocksObject
        implements DBOptionsInterface<Options>, ColumnFamilyOptionsInterface<Options>,
        MutableColumnFamilyOptionsInterface<Options> {
      static {
        RocksDB.loadLibrary();
      }

      进入到RocksDB类,实例化rocksDB,先读取是否已加载标志位,没加载过才会去加载:

    /**
       * Loads the necessary library files.
       * Calling this method twice will have no effect.
       * By default the method extracts the shared library for loading at
       * java.io.tmpdir, however, you can override this temporary location by
       * setting the environment variable ROCKSDB_SHAREDLIB_DIR.
       */
      public static void loadLibrary() {
        if (libraryLoaded.get() == LibraryState.LOADED) {
          return;
        }
    
        if (libraryLoaded.compareAndSet(LibraryState.NOT_LOADED,
            LibraryState.LOADING)) {
          final String tmpDir = System.getenv("ROCKSDB_SHAREDLIB_DIR");
          // loading possibly necessary libraries.
          for (final CompressionType compressionType : CompressionType.values()) {
            try {
              if (compressionType.getLibraryName() != null) {
                System.loadLibrary(compressionType.getLibraryName());
              }
            } catch (UnsatisfiedLinkError e) {
              // since it may be optional, we ignore its loading failure here.
            }
          }
          try {
            NativeLibraryLoader.getInstance().loadLibrary(tmpDir);
          } catch (IOException e) {
            libraryLoaded.set(LibraryState.NOT_LOADED);
            throw new RuntimeException("Unable to load the RocksDB shared library"
                + e);
          }
    
          libraryLoaded.set(LibraryState.LOADED);
          return;
        }
    
        while (libraryLoaded.get() == LibraryState.LOADING) {
          try {
            Thread.sleep(10);
          } catch(final InterruptedException e) {
            //ignore
          }
        }
      }

      注意一点,临时目录是从环境变量ROCKSDB_SHAREDLIB_DIR读取的,所以可以通过设置该环境变量改变临时目录路径(日志里的C:UsersAdministratorAppDataLocalTemplibrocksdbjni3696928169151614297.dll)。接着进入到NativeLibraryLoader看RocksDB的实例化详情:

    /**
       * Firstly attempts to load the library from <i>java.library.path</i>,
       * if that fails then it falls back to extracting
       * the library from the classpath
       * {@link org.rocksdb.NativeLibraryLoader#loadLibraryFromJar(java.lang.String)}
       *
       * @param tmpDir A temporary directory to use
       *   to copy the native library to when loading from the classpath.
       *   If null, or the empty string, we rely on Java's
       *   {@link java.io.File#createTempFile(String, String)}
       *   function to provide a temporary location.
       *   The temporary file will be registered for deletion
       *   on exit.
       *
       * @throws java.io.IOException if a filesystem operation fails.
       */
      public synchronized void loadLibrary(final String tmpDir) throws IOException {
        try {
            System.loadLibrary(sharedLibraryName);
        } catch(final UnsatisfiedLinkError ule1) {
          try {
            System.loadLibrary(jniLibraryName);
          } catch(final UnsatisfiedLinkError ule2) {
            loadLibraryFromJar(tmpDir);
          }
        }
      }
    
      /**
       * Attempts to extract the native RocksDB library
       * from the classpath and load it
       *
       * @param tmpDir A temporary directory to use
       *   to copy the native library to. If null,
       *   or the empty string, we rely on Java's
       *   {@link java.io.File#createTempFile(String, String)}
       *   function to provide a temporary location.
       *   The temporary file will be registered for deletion
       *   on exit.
       *
       * @throws java.io.IOException if a filesystem operation fails.
       */
      void loadLibraryFromJar(final String tmpDir)
          throws IOException {
        if (!initialized) {
          System.load(loadLibraryFromJarToTemp(tmpDir).getAbsolutePath());
          initialized = true;
        }
      }
    
      File loadLibraryFromJarToTemp(final String tmpDir)
              throws IOException {
        final File temp;
        if (tmpDir == null || tmpDir.isEmpty()) {
          temp = File.createTempFile(tempFilePrefix, tempFileSuffix);
        } else {
          temp = new File(tmpDir, jniLibraryFileName);
          if (temp.exists() && !temp.delete()) {
            throw new RuntimeException("File: " + temp.getAbsolutePath()
                + " already exists and cannot be removed.");
          }
          if (!temp.createNewFile()) {
            throw new RuntimeException("File: " + temp.getAbsolutePath()
                + " could not be created.");
          }
        }
    
        if (!temp.exists()) {
          throw new RuntimeException("File " + temp.getAbsolutePath() + " does not exist.");
        } else {
          temp.deleteOnExit();
        }
    
        // attempt to copy the library from the Jar file to the temp destination
        try (final InputStream is = getClass().getClassLoader().
          getResourceAsStream(jniLibraryFileName)) {
          if (is == null) {
            throw new RuntimeException(jniLibraryFileName + " was not found inside JAR.");
          } else {
            Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
          }
        }
    
        return temp;
      }

      先从sharedLibraryName(rocksdbjni)实例化,再从jniLibraryName(rocksdbjni-win64)实例化,最后从临时目录实例化。第一步是从JDK环境变量(即java.library.path,本机是D:DevJavajdk1.8.0_102jrein)加载rocksdbjni,失败再从类路径加载rocksdbjni-win64,最后从本地临时目录加载librocksdbjni-win64.dll。这三部曲是rocksDB实例化的精髓。而最后一步是最复杂的,需要创建一个临时文件,然后从rocksdbjni这个jar包中把librocksdbjni-win64.dll复制到本地C:UsersAdministratorAppDataLocalTemplibrocksdbjni3696928169151614297.dll,最后用org.rocksdb.NativeLibraryLoader这个类加载器来加载librocksdbjni3696928169151614297.dll得到rocksdb的实例,然后把这个DLL文件加入到加载类库中,后续容器重复加载时无需再次复制DLL文件。

      上面的三部曲都需要利用java.lang包的工具来进行类加载,用的到类有System、Runtime和ClassLoader:

        /**
         * Loads the native library specified by the filename argument.  The filename
         * argument must be an absolute path name.
         *
         * If the filename argument, when stripped of any platform-specific library
         * prefix, path, and file extension, indicates a library whose name is,
         * for example, L, and a native library called L is statically linked
         * with the VM, then the JNI_OnLoad_L function exported by the library
         * is invoked rather than attempting to load a dynamic library.
         * A filename matching the argument does not have to exist in the
         * file system.
         * See the JNI Specification for more details.
         *
         * Otherwise, the filename argument is mapped to a native library image in
         * an implementation-dependent manner.
         *
         * <p>
         * The call <code>System.load(name)</code> is effectively equivalent
         * to the call:
         * <blockquote><pre>
         * Runtime.getRuntime().load(name)
         * </pre></blockquote>
         *
         * @param      filename   the file to load.
         * @exception  SecurityException  if a security manager exists and its
         *             <code>checkLink</code> method doesn't allow
         *             loading of the specified dynamic library
         * @exception  UnsatisfiedLinkError  if either the filename is not an
         *             absolute path name, the native library is not statically
         *             linked with the VM, or the library cannot be mapped to
         *             a native library image by the host system.
         * @exception  NullPointerException if <code>filename</code> is
         *             <code>null</code>
         * @see        java.lang.Runtime#load(java.lang.String)
         * @see        java.lang.SecurityManager#checkLink(java.lang.String)
         */
        @CallerSensitive
        public static void load(String filename) {
            Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
        }
        /**
         * Loads the native library specified by the filename argument.  The filename
         * argument must be an absolute path name.
         * (for example
         * <code>Runtime.getRuntime().load("/home/avh/lib/libX11.so");</code>).
         *
         * If the filename argument, when stripped of any platform-specific library
         * prefix, path, and file extension, indicates a library whose name is,
         * for example, L, and a native library called L is statically linked
         * with the VM, then the JNI_OnLoad_L function exported by the library
         * is invoked rather than attempting to load a dynamic library.
         * A filename matching the argument does not have to exist in the file
         * system. See the JNI Specification for more details.
         *
         * Otherwise, the filename argument is mapped to a native library image in
         * an implementation-dependent manner.
         * <p>
         * First, if there is a security manager, its <code>checkLink</code>
         * method is called with the <code>filename</code> as its argument.
         * This may result in a security exception.
         * <p>
         * This is similar to the method {@link #loadLibrary(String)}, but it
         * accepts a general file name as an argument rather than just a library
         * name, allowing any file of native code to be loaded.
         * <p>
         * The method {@link System#load(String)} is the conventional and
         * convenient means of invoking this method.
         *
         * @param      filename   the file to load.
         * @exception  SecurityException  if a security manager exists and its
         *             <code>checkLink</code> method doesn't allow
         *             loading of the specified dynamic library
         * @exception  UnsatisfiedLinkError  if either the filename is not an
         *             absolute path name, the native library is not statically
         *             linked with the VM, or the library cannot be mapped to
         *             a native library image by the host system.
         * @exception  NullPointerException if <code>filename</code> is
         *             <code>null</code>
         * @see        java.lang.Runtime#getRuntime()
         * @see        java.lang.SecurityException
         * @see        java.lang.SecurityManager#checkLink(java.lang.String)
         */
        @CallerSensitive
        public void load(String filename) {
            load0(Reflection.getCallerClass(), filename);
        }
    
        synchronized void load0(Class<?> fromClass, String filename) {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkLink(filename);
            }
            if (!(new File(filename).isAbsolute())) {
                throw new UnsatisfiedLinkError(
                    "Expecting an absolute path of the library: " + filename);
            }
            ClassLoader.loadLibrary(fromClass, filename, true);
        }
        // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
        static void loadLibrary(Class<?> fromClass, String name,
                                boolean isAbsolute) {
            ClassLoader loader =
                (fromClass == null) ? null : fromClass.getClassLoader();
            if (sys_paths == null) {
                usr_paths = initializePath("java.library.path");
                sys_paths = initializePath("sun.boot.library.path");
            }
            if (isAbsolute) {
                if (loadLibrary0(fromClass, new File(name))) {
                    return;
                }
                throw new UnsatisfiedLinkError("Can't load library: " + name);
            }
            if (loader != null) {
                String libfilename = loader.findLibrary(name);
                if (libfilename != null) {
                    File libfile = new File(libfilename);
                    if (!libfile.isAbsolute()) {
                        throw new UnsatisfiedLinkError(
        "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
                    }
                    if (loadLibrary0(fromClass, libfile)) {
                        return;
                    }
                    throw new UnsatisfiedLinkError("Can't load " + libfilename);
                }
            }
            for (int i = 0 ; i < sys_paths.length ; i++) {
                File libfile = new File(sys_paths[i], System.mapLibraryName(name));
                if (loadLibrary0(fromClass, libfile)) {
                    return;
                }
                libfile = ClassLoaderHelper.mapAlternativeName(libfile);
                if (libfile != null && loadLibrary0(fromClass, libfile)) {
                    return;
                }
            }
            if (loader != null) {
                for (int i = 0 ; i < usr_paths.length ; i++) {
                    File libfile = new File(usr_paths[i],
                                            System.mapLibraryName(name));
                    if (loadLibrary0(fromClass, libfile)) {
                        return;
                    }
                    libfile = ClassLoaderHelper.mapAlternativeName(libfile);
                    if (libfile != null && loadLibrary0(fromClass, libfile)) {
                        return;
                    }
                }
            }
            // Oops, it failed
            throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
        }
        private static boolean loadLibrary0(Class<?> fromClass, final File file) {
            // Check to see if we're attempting to access a static library
            String name = findBuiltinLib(file.getName());
            boolean isBuiltin = (name != null);
            if (!isBuiltin) {
                boolean exists = AccessController.doPrivileged(
                    new PrivilegedAction<Object>() {
                        public Object run() {
                            return file.exists() ? Boolean.TRUE : null;
                        }})
                    != null;
                if (!exists) {
                    return false;
                }
                try {
                    name = file.getCanonicalPath();
                } catch (IOException e) {
                    return false;
                }
            }
            ClassLoader loader =
                (fromClass == null) ? null : fromClass.getClassLoader();
            Vector<NativeLibrary> libs =
                loader != null ? loader.nativeLibraries : systemNativeLibraries;
            synchronized (libs) {
                int size = libs.size();
                for (int i = 0; i < size; i++) {
                    NativeLibrary lib = libs.elementAt(i);
                    if (name.equals(lib.name)) {
                        return true;
                    }
                }
    
                synchronized (loadedLibraryNames) {
                    if (loadedLibraryNames.contains(name)) {
                        throw new UnsatisfiedLinkError
                            ("Native Library " +
                             name +
                             " already loaded in another classloader");
                    }
                    /* If the library is being loaded (must be by the same thread,
                     * because Runtime.load and Runtime.loadLibrary are
                     * synchronous). The reason is can occur is that the JNI_OnLoad
                     * function can cause another loadLibrary invocation.
                     *
                     * Thus we can use a static stack to hold the list of libraries
                     * we are loading.
                     *
                     * If there is a pending load operation for the library, we
                     * immediately return success; otherwise, we raise
                     * UnsatisfiedLinkError.
                     */
                    int n = nativeLibraryContext.size();
                    for (int i = 0; i < n; i++) {
                        NativeLibrary lib = nativeLibraryContext.elementAt(i);
                        if (name.equals(lib.name)) {
                            if (loader == lib.fromClass.getClassLoader()) {
                                return true;
                            } else {
                                throw new UnsatisfiedLinkError
                                    ("Native Library " +
                                     name +
                                     " is being loaded in another classloader");
                            }
                        }
                    }
                    NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);
                    nativeLibraryContext.push(lib);
                    try {
                        lib.load(name, isBuiltin);
                    } finally {
                        nativeLibraryContext.pop();
                    }
                    if (lib.loaded) {
                        loadedLibraryNames.addElement(name);
                        libs.addElement(lib);
                        return true;
                    }
                    return false;
                }
            }
        }

       这里拿三部曲最后一部举例说明下:参数fromClass就是调用System.load方法所在的类,这里是rocksDB的加载库类org.rocksdb.NativeLibraryLoader,另一个参数File就是C:UsersAdministratorAppDataLocalTemplibrocksdbjni3696928169151614297.dll,从NativeLibraryLoader类加载librocksdbjni5581206381055061043.dll后,把这个DLL文件放入loadedLibraryNames这个Vector,后续重复加载直接从该Vector取,无需再从rocksdbjni的jar包中复制DLL文件。

      跟踪到这里,问题代码已经浮出水面:

    lib.load(name, isBuiltin);

      这个load方法是ClassLoader类的内部类NativeLibrary的原生方法,动态链接库加载就是从这里进入DLL文件里具体加载方法的

    native void load(String name, boolean isBuiltin);

      从这个load出来就是UnsatisfiedLinkError。所以问题的焦点转移到了DLL文件本身,用Dependency Walker打开一看,有错误提示:

    Error: Modules with different CPU types were found.

      继续跟进,发现其中一个文件叫IEShims.dll显示是X86,而我本机是X64的。替换该文件,Dependency Walker不再报错,但跑代码发现依然报错。

      问题解决:捕获rockdbs异常,记录日志,跳过,继续启动加载spring容器。该DLL的加载涉及太多因素,无法一一排查,只能吃掉异常来规避,rocksdb加载失败对主业务无太大影响。

  • 相关阅读:
    使用 Promise.all 同时发起多个请求
    vite 开发 Cesium 程序最佳配置实践
    【linux学习】使用grep命令获取过滤的数据作为下个命令的入参
    记一次k8s depolyment失败处理
    powerdesigner导出excel数据字典
    vue 时间格式
    ASP.NET MVC4 跨域配置
    Win10系统中切换虚拟桌面的快捷键如何设置
    不顾一切最简NHinbernate配置并读写数据库
    Windows time_wait过多解决办法
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/7780188.html
Copyright © 2011-2022 走看看