java.lang.UnsatisfiedLinkError no *****.dll in jav

2019-01-01 03:59发布

问题:

How can I load a custom dll file in my web application? I tried following ways but its failing.

  • copied all required dlls in system32 folder and tried to load one of them in Servlet constructor System.loadLibrary
  • Copied required dlls in tomcat_home/shared/lib and tomcat_home/common/lib
  • all these dlls are in WEB-INF/lib of the web-application

回答1:

In order for System.loadLibrary() to work, the library (on Windows, a DLL) must be in a directory somewhere on your PATH or on a path listed in the java.library.path system property (so you can launch Java like java -Djava.library.path=/path/to/dir).

Additionally, for loadLibrary(), you specify the base name of the library, without the .dll at the end. So, for /path/to/something.dll, you would just use System.loadLibrary(\"something\").

You also need to look at the exact UnsatisfiedLinkError that you are getting. If it says something like:

Exception in thread \"main\" java.lang.UnsatisfiedLinkError: no foo in java.library.path

then it can\'t find the foo library (foo.dll) in your PATH or java.library.path. If it says something like:

Exception in thread \"main\" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V

then something is wrong with the library itself in the sense that Java is not able to map a native Java function in your application to its actual native counterpart.

To start with, I would put some logging around your System.loadLibrary() call to see if that executes properly. If it throws an exception or is not in a code path that is actually executed, then you will always get the latter type of UnsatisfiedLinkError explained above.

As a sidenote, most people put their loadLibrary() calls into a static initializer block in the class with the native methods, to ensure that it is always executed exactly once:

class Foo {

    static {
        System.loadLibrary(\'foo\');
    }

    public Foo() {
    }

}


回答2:

Changing \'java.library.path\' variable at runtime is not enough because it is read only once by JVM. You have to reset it like:

System.setProperty(\"java.library.path\", path);
//set sys_paths to null
final Field sysPathsField = ClassLoader.class.getDeclaredField(\"sys_paths\");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);

Please, take a loot at: Changing Java Library Path at Runtime.



回答3:

The original answer by Adam Batkin will lead you to a solution, but if you redeploy your webapp (without restarting your web container), you should run into the following error:

java.lang.UnsatisfiedLinkError: Native Library \"foo\" already loaded in another classloader
   at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715)
   at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646)
   at java.lang.Runtime.load0(Runtime.java:787)
   at java.lang.System.load(System.java:1022)

This happens because the ClassLoader that originally loaded your DLL still references this DLL. However, your webapp is now running with a new ClassLoader, and because the same JVM is running and a JVM won\'t allow 2 references to the same DLL, you can\'t reload it. Thus, your webapp can\'t access the existing DLL and can\'t load a new one. So.... you\'re stuck.

Tomcat\'s ClassLoader documentation outlines why your reloaded webapp runs in a new isolated ClassLoader and how you can work around this limitation (at a very high level).

The solution is to extend Adam Batkin\'s solution a little:

   package awesome;

   public class Foo {

        static {
            System.loadLibrary(\'foo\');
        }

        // required to work with JDK 6 and JDK 7
        public static void main(String[] args) {
        }

    }

Then placing a jar containing JUST this compiled class into the TOMCAT_HOME/lib folder.

Now, within your webapp, you just have to force Tomcat to reference this class, which can be done as simply as this:

  Class.forName(\"awesome.Foo\");

Now your DLL should be loaded in the common classloader, and can be referenced from your webapp even after being redeployed.

Make sense?

A working reference copy can be found on google code, static-dll-bootstrapper .



回答4:

You can use System.load() to provide an absolute path which is what you want, rather than a file in the standard library folder for the respective OS.

If you want native applications that already exist, use System.loadLibrary(String filename). If you want to provide your own you\'re probably better with load().

You should also be able to use loadLibrary with the java.library.path set correctly. See ClassLoader.java for implementation source showing both paths being checked (OpenJDK)



回答5:

In the case where the problem is that System.loadLibrary cannot find the DLL in question, one common misconception (reinforced by Java\'s error message) is that the system property java.library.path is the answer. If you set the system property java.library.path to the directory where your DLL is located, then System.loadLibrary will indeed find your DLL. However, if your DLL in turn depends on other DLLs, as is often the case, then java.library.path cannot help, because the loading of the dependent DLLs is managed entirely by the operating system, which knows nothing of java.library.path. Thus, it is almost always better to bypass java.library.path and simply add your DLL\'s directory to LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS), or Path (Windows) prior to starting the JVM.

(Note: I am using the term \"DLL\" in the generic sense of DLL or shared library.)



回答6:

If you need to load a file that\'s relative to some directory where you already are (like in the current directory), here\'s an easy solution:

File f;

if (System.getProperty(\"sun.arch.data.model\").equals(\"32\")) {
    // 32-bit JVM
    f = new File(\"mylibfile32.so\");
} else {
    // 64-bit JVM
    f = new File(\"mylibfile64.so\");
}
System.load(f.getAbsolutePath());


回答7:

For those who are looking for java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

I was facing same exception; I tried everything and important things to make it work are:

  1. Correct version of pdf lib.jar ( In my case it was wrong version jar kept in server runtime )
  2. Make a folder and keep the pdflib jar in it and add the folder in your PATH variable

It worked with tomcat 6.



回答8:

Poor me ! spent a whole day behind this.Writing it down here if any body replicates this issue.

I was trying to load as Adam suggested but then got caught with AMD64 vs IA 32 exception.If in any case after working as per Adam\'s(no doubt the best pick) walkthrough,try to have a 64 bit version of latest jre.Make sure your JRE AND JDK are 64 bit and you have correctly added it to your classpath.

My working example goes here:unstatisfied link error



回答9:

  1. If you believe that you added a path of native lib to %PATH%, test yourself one more time by:

    System.out.println(System.getProperty(\"java.library.path\"))

It should show you actually if your dll is on %PATH%

  1. Do restart IDE Idea, yes, it appeared to work for me after i setting up env variable with adding it to the %PATH%


回答10:

For windows I found that when i loaded the filles(jd2xsx.dll calls & ftd2xx.dll) into the windowws/system32 folder this resolved the issues. I then had an issue with my newer fd2xx.dll having to do with parameters which is why I had to load the older version of this dll. I will have to ferrit this out later.

Note: the jd2xsx.dll calls the ftd2xx.dll so just setting the path for the jd2xx.dll might not work.



回答11:

I\'m using Mac OS X Yosemite and Netbeans 8.02, I got the same error and the simple solution I have found is like above, this is useful when you need to include native library in the project. So do the next for Netbeans:

1.- Right click on the Project
2.- Properties
3.- Click on RUN
4.- VM Options: java -Djava.library.path=\"your_path\"
5.- for example in my case: java -Djava.library.path=</Users/Lexynux/NetBeansProjects/NAO/libs>
6.- Ok

I hope it could be useful for someone. The link where I found the solution is here: java.library.path – What is it and how to use



回答12:

I had the same problem and the error was due to a rename of the dll. It could happen that the library name is also written somewhere inside the dll. When I put back its original name I was able to load using System.loadLibrary



回答13:

This is My java.library.path:

 java.library.path = C:\\Program Files\\Java\\jdk1.7.0_51\\bin
     C:\\WINDOWS\\Sun\\Java\\bin
     C:\\WINDOWS\\system32
     C:\\WINDOWS
     C:\\WINDOWS\\system32
     C:\\Program Files\\I.R.I.S. SA\\iDRS_15_2_for_Win64_15_2_11_1717\\lib\\idrskr
.lib
     C:\\Program Files\\I.R.I.S. SA\\iDRS_15_2_for_Win64_15_2_11_1717\\bin\\iDRMSG
idgeDll.dll
     C:\\Program Files\\I.R.I.S. SA\\iDRS_15_2_for_Win64_15_2_11_1717\\bin\\iDRMSG
aderDll.dll
     C:\\Program Files\\Java\\jdk1.7.0_51\\bin
     C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include
     C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib
     C:\\WINDOWS\\System32\\Wbem
     C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0
     C:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\
     C:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn

Still rror comes: 
infile >> D:\\pdf_upload\\pre_idrs15_win_temporary_license_activation_tutorial.pdf
outFile >> D:\\pdf_upload\\processed\\pre_idrs15_win_temporary_license_activation_tutorial.txt
Hello : This is java library path:(NICKRJ) C:\\Program Files\\Java\\jdk1.7.0_51\\bin;C:\\WINDOWS\\Sun\\Java\\bin;C:\\WINDOWS\\system32;C:\\WINDOWS;C:/Program Files/Java/jdk1.7.0_51/jre/bin/server;C:/Program Files/Java/jdk1.7.0_51/jre/bin;C:/Program Files/Java/jdk1.7.0_51/jre/lib/amd64;C:\\WINDOWS\\system32;C:\\Program Files\\I.R.I.S. SA\\iDRS_15_2_for_Win64_15_2_11_1717\\lib\\idrskrn15.lib;C:\\Program Files\\I.R.I.S. SA\\iDRS_15_2_for_Win64_15_2_11_1717\\bin\\iDRMSGEBridgeDll.dll;C:\\Program Files\\I.R.I.S. SA\\iDRS_15_2_for_Win64_15_2_11_1717\\bin\\iDRMSGEReaderDll.dll;C:\\Program Files\\Java\\jdk1.7.0_51\\bin;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn;D:\\WorkSet\\New folder\\eclipse_kepler\\eclipse;;.
Exception in thread \"main\" java.lang.UnsatisfiedLinkError: no iDRMSGEBridgeDll in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
    at java.lang.Runtime.loadLibrary0(Runtime.java:849)
    at java.lang.System.loadLibrary(System.java:1088)
    at com.bi.iDRMSGEBridgeDll.callOcr(iDRMSGEBridgeDll.java:78)
    at com.bi.iDRMSGEBridgeDll.main(iDRMSGEBridgeDll.java:15)


Here is my Java JNI class:

package com.bi;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

public class iDRMSGEBridgeDll  
{
  public native int iDRMSGEDll_Initialize(String strPropertiesFileName);
  public native int iDRMSGEDll_VerifyLicense();
  public native int iDRMSGEDll_ConvertFile(String strSourceFileName, String srcOutputFileName,  String formatType);
  public native int iDRMSGEDll_Finalize();

public static void main(String[] args)
{
    //iDRMSGEBridgeDll.callOcr(\"bgimage.jpg\",\"jpg\",\"\",\"d:\\\\\",\"d:\\\\\",\"4\");
    iDRMSGEBridgeDll.callOcr(\"pre_idrs15_win_temporary_license_activation_tutorial.pdf\",\"pdf\",\"\",\"D:\\\\pdf_upload\",\"D:\\\\pdf_upload\\\\processed\",\"4\");


    /*  System.loadLibrary(\"iDRMSGEBridgeDll\");
        iDRMSGEBridgeDll obj = new iDRMSGEBridgeDll();
        if ( obj.iDRMSGEDll_Initialize(\"D:\\\\iris\\\\iDRSGEDll.properties\") != 0 ) {
            obj.iDRMSGEDll_Finalize();
            return;
        }
        System.out.println(\"iDRMSGEDll_Initialize success.\");
        if ( obj.iDRMSGEDll_VerifyLicense() != 0 ) {
            obj.iDRMSGEDll_Finalize();
            return;
        }
        System.out.println(\"iDRMSGEDll_VerifyLicense success.\");
        if (obj.iDRMSGEDll_ConvertFile(\"E:\\\\UI changes File_by Shakti\\\\PDF\\\\S14-005_FRAMEWORK_AGREEMENT_FOR_ENGINE_MAINTENANCE_SERVICES_EASYJET[1].pdf\", 
            \"E:\\\\SK_Converted_Files\\\\MVP_CONTRACTS\\\\Southwest CFM56-7\\\\S14-005_FRAMEWORK_AGREEMENT_FOR_ENGINE_MAINTENANCE_SERVICES_EASYJET[1]\\\\S14-005_FRAMEWORK_AGREEMENT_FOR_ENGINE_MAINTENANCE_SERVICES_EASYJET[1].txt\", \"4\" ) != 0 ) {
            obj.iDRMSGEDll_Finalize();
            return;
        }
        System.out.println(\"iDRMSGEDll_ConvertFile 1 success.\");
        /*if (obj.iDRMSGEDll_ConvertFile(\"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_200dpi.pdf\", 
            \"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_200dpi.out\", 4) != 0 ) {
            obj.iDRMSGEDll_Finalize();
            return;
        }
        System.out.println(\"iDRMSGEDll_ConvertFile 2 success.\");
        if (obj.iDRMSGEDll_ConvertFile(\"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_300dpi.pdf\", 
            \"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_300dpi.out\", 4) != 0 ) {
            obj.iDRMSGEDll_Finalize();
            return;
        }
        System.out.println(\"iDRMSGEDll_ConvertFile 3 success.\");
        if (obj.iDRMSGEDll_ConvertFile(\"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan2_300dpi.pdf\", 
            \"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan2_300dpi.out\", 4) != 0 ) {
            obj.iDRMSGEDll_Finalize();
            return;
        }
        System.out.println(\"iDRMSGEDll_ConvertFile 4 success.\");
        obj.iDRMSGEDll_Finalize();
        System.out.println(\"iDRMSGEDll_Finalize success.\");
        return;*/

}
    public static String callOcr(String inputFile, String docType, String engineType, String filePath,String outputFolder,String type) throws RuntimeException
    {
        String message =  \"\";
        String formatType = type;           
        String inFile = filePath +\"\\\\\" +inputFile;
        String outFile=\"\";
        if(type.equals(\"4\"))
        outFile = outputFolder +\"\\\\\"+inputFile.substring(0,inputFile.lastIndexOf(\".\"))+\".txt\";
        else if(type.equals(\"6\"))
            outFile = outputFolder +\"\\\\\"+inputFile.substring(0,inputFile.lastIndexOf(\".\"))+\".rtf\";
        else if(type.equals(\"9\"))
            outFile = outputFolder +\"\\\\\"+inputFile.substring(0,inputFile.lastIndexOf(\".\"))+\".pdf\";
        else
            outFile = outputFolder +\"\\\\\"+inputFile.substring(0,inputFile.lastIndexOf(\".\"))+\".csv\";

        System.out.println(\"infile >> \"+inFile);
        System.out.println(\"outFile >> \"+outFile);
        System.out.println(\"Hello : This is java library path:(NICKRJ) \" +System.getProperty(\"java.library.path\"));

        System.loadLibrary(\"iDRMSGEBridgeDll\");
        //System.load(\"C:\\\\Program Files (x86)\\\\I.R.I.S. SA\\\\iDRS_15_2_for_Win64_15_2_11_1717\\bin\\\\iDRMSGEBridgeDll.dll\");
        //Runtime.getRuntime().loadLibrary(\"iDRMSGEBridgeDll\");

            iDRMSGEBridgeDll obj = new iDRMSGEBridgeDll();
        try
        {
            if ( obj.iDRMSGEDll_Initialize(\"D:\\\\IRIS\\\\iDRSGEDll.properties\") != 0 ) {
                obj.iDRMSGEDll_Finalize();
            //  return ; 
            }
            System.out.println(\"iDRMSGEDll_Initialize success.\");
            if ( obj.iDRMSGEDll_VerifyLicense() != 0 ) {
                obj.iDRMSGEDll_Finalize();
        //      return;
            }
            System.out.println(\"iDRMSGEDll_VerifyLicense success.\");
        //  formatType= JOptionPane.showInputDialog(\"Please input mark format type: \");
            if (formatType!=null && formatType.equals(\"4\"))  {
                obj.iDRMSGEDll_ConvertFile(inFile, 
                        outFile, \"4\" ); 
                obj.iDRMSGEDll_Finalize();
        //      return;
            }
            else if(formatType!=null && formatType.equals(\"6\")) {
                obj.iDRMSGEDll_ConvertFile(inFile, 
                        outFile, \"6\" ); 
                    obj.iDRMSGEDll_Finalize();
            //      return;
                }   
            else if(formatType!=null && formatType.equals(\"7\")) {
                obj.iDRMSGEDll_ConvertFile(inFile, 
                        outFile, \"7\" ); 
                    obj.iDRMSGEDll_Finalize();
            //      return;
                }
            else if(formatType!=null && formatType.equals(\"9\")) {
                obj.iDRMSGEDll_ConvertFile(inFile, 
                        outFile, \"9\" ); 
                    obj.iDRMSGEDll_Finalize();
            //      return;
                }
            else
            {
            message= \"iDRMSGEDll_VerifyLicense failure\";
            }

            System.out.println(\"iDRMSGEDll_ConvertFile 1 success.\");
            /*if (obj.iDRMSGEDll_ConvertFile(\"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_200dpi.pdf\", 
                \"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_200dpi.out\", 4) != 0 ) {
                obj.iDRMSGEDll_Finalize();
                return;
            }
            System.out.println(\"iDRMSGEDll_ConvertFile 2 success.\");
            if (obj.iDRMSGEDll_ConvertFile(\"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_300dpi.pdf\", 
                \"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan1_300dpi.out\", 4) != 0 ) {
                obj.iDRMSGEDll_Finalize();
                return;
            }
            System.out.println(\"iDRMSGEDll_ConvertFile 3 success.\");
            if (obj.iDRMSGEDll_ConvertFile(\"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan2_300dpi.pdf\", 
                \"C:\\\\Software\\\\iDRS_15_1_7_2304\\\\sample_pdfs\\\\scan2_300dpi.out\", 4) != 0 ) {
                obj.iDRMSGEDll_Finalize();
                return;
            }
            System.out.println(\"iDRMSGEDll_ConvertFile 4 success.\");*/
            obj.iDRMSGEDll_Finalize();
            System.out.println(\"iDRMSGEDll_Finalize success.\");
            if(message.length()==0)
            {
                message = \"success\";
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
            message = e.getMessage();
        }

        return message;





    }


}