Pergunta

Como posso carregar um arquivo DLL personalizado no meu aplicativo da web? Eu tentei seguir maneiras, mas está falhando.

  • copiou todas as DLLs necessárias em system32 pasta e tentou carregar um deles em Servlet construtor System.loadLibrary
  • Copiaram DLLs necessários em tomcat_home/shared/lib e tomcat_home/common/lib
  • Todas essas DLLs estão em WEB-INF/lib da aplicação da web
Foi útil?

Solução

Para System.loadLibrary() Para trabalhar, a biblioteca (no Windows, uma DLL) deve estar em um diretório em algum lugar do seu PATH ou em um caminho listado no java.library.path Propriedade do sistema (para que você possa lançar o Java como java -Djava.library.path=/path/to/dir).

Além disso, para loadLibrary(), você especifica o nome base da biblioteca, sem o .dll no final. Então, para /path/to/something.dll, você apenas usaria System.loadLibrary("something").

Você também precisa olhar para o exato UnsatisfiedLinkError que você está recebendo. Se diz algo como:

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

Então não pode encontrar o foo biblioteca (foo.dll) em seu PATH ou java.library.path. Se diz algo como:

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

Então, algo está errado com a própria biblioteca, no sentido de que o Java não pode mapear uma função Java nativa em seu aplicativo para sua contraparte nativa real.

Para começar, eu colocaria alguns logs em torno do seu System.loadLibrary() Ligue para ver se isso é executado corretamente. Se ele lançar uma exceção ou não estiver em um caminho de código que seja realmente executado, você sempre obterá o último tipo de UnsatisfiedLinkError explicado acima.

Como uma boneca, a maioria das pessoas coloca seus loadLibrary() chama um bloco de inicializador estático na classe com os métodos nativos, para garantir que ele sempre seja executado exatamente uma vez:

class Foo {

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

    public Foo() {
    }

}

Outras dicas

Alterar a variável 'java.library.path' no tempo de execução não é suficiente porque é lida apenas uma vez pela JVM. Você tem que redefini -lo como:

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);

Por favor, tome um saque em: Alterando o caminho da biblioteca Java em tempo de execução.

A resposta original de Adam Batkin o levará a uma solução, mas se você reimplavar seu WebApp (sem reiniciar o contêiner da web), você deve enfrentar o seguinte erro:

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)

Isso acontece porque o carregador de classe que originalmente carregou sua DLL ainda faz referência a esta DLL. No entanto, seu WebApp agora está executando com um novo carregador de classe e, como a mesma JVM está em execução e uma JVM não permitirá 2 referências à mesma DLL, você não pode recarregar isto. Assim, seu WebApp não pode acessar a DLL existente e não pode carregar uma nova. Então .... você está preso.

Documentação do carregador de classe Tomcat descreve por que o seu WebApp recarregado é executado em um novo carregador de classe isolado e como você pode contornar essa limitação (em um nível muito alto).

A solução é estender um pouco a solução de Adam Batkin:

   package awesome;

   public class Foo {

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

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

    }

Em seguida, colocando uma jarra contendo apenas essa classe compilada na pasta tomcat_home/lib.

Agora, dentro do seu WebApp, você só precisa forçar o Tomcat a fazer referência a esta classe, que pode ser feita tão simplesmente quanto a seguinte:

  Class.forName("awesome.Foo");

Agora, sua DLL deve ser carregada no carregador de classe comum e pode ser referenciada no seu WebApp, mesmo depois de ser reimplantado.

Faz sentido?

Uma cópia de referência de trabalho pode ser encontrada no código do Google, static-dll-bootstrapper .

Você pode usar System.load() Fornecer um caminho absoluto que é o que você deseja, em vez de um arquivo na pasta da biblioteca padrão para o respectivo sistema operacional.

Se você deseja aplicativos nativos que já existem, use System.loadLibrary(String filename). Se você deseja fornecer o seu próprio, provavelmente é melhor com o carregamento ().

Você também deve ser capaz de usar loadLibrary com o java.library.path Defina corretamente. Ver ClassLoader.java Para a fonte de implementação mostrando os dois caminhos sendo verificados (OpenJDK)

No caso em que o problema é que o System.Loadlibrary não pode encontrar a DLL em questão, um equívoco comum (reforçado pela mensagem de erro de Java) é que a propriedade do sistema java.library.Path é a resposta. Se você definir a propriedade do sistema java.library.path para o diretório em que sua DLL está localizada, o System.LoadLibrary encontrará sua DLL. No entanto, se sua DLL, por sua vez, depende de outras DLLs, como costuma ser o caso, o java.library.Path não pode ajudar, porque o carregamento das DLLs dependentes é gerenciado inteiramente pelo sistema operacional, que não sabe nada da Java.library. caminho. Portanto, é quase sempre melhor ignorar o java.library.Path e simplesmente adicionar o diretório da sua DLL a ld_library_path (linux), dyld_library_path (macOS) ou caminho (Windows) antes de iniciar a JVM.

(Nota: estou usando o termo "dll" no sentido genérico de DLL ou biblioteca compartilhada.)

Se você precisar carregar um arquivo em relação a algum diretório onde você já está (como no diretório atual), aqui está uma solução fácil:

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());

Para aqueles que estão procurando java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

Eu estava enfrentando a mesma exceção; Eu tentei de tudo e coisas importantes para fazê -lo funcionar:

  1. Versão correta do pdf lib.jar (no meu caso, foi o frasco de versão errado mantida no servidor tempo de execução)
  2. Faça uma pasta e mantenha a jarra pdflib nela e adicione a pasta na sua variável de caminho

Funcionou com o Tomcat 6.

Pobre eu! passou um dia inteiro atrás disso. Escritando aqui se algum corpo replicar esse problema.

Eu estava tentando carregar como Adam sugeriu, mas depois fui pego com a exceção AMD64 vs IA 32.Se, em qualquer caso, depois de trabalhar de acordo com o passo a passo de Adam (sem dúvida, a melhor escolha), tente ter uma versão de 64 bits do mais recente Jre.Make com certeza Seu JRE e JDK são de 64 bits e você o adicionou corretamente ao seu caminho de classe.

Meu exemplo de trabalho vai aqui:Erro de link não satisfatório

  1. Se você acredita que adicionou um caminho de Lib nativo a %Path %, teste -se mais uma vez:

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

Deve mostrar você realmente se sua DLL estiver no %Path %

  1. Reinicie a ideia do IDE, sim, parecia funcionar para mim depois de configurar a variável Env ao adicioná -la ao %Path %

Para o Windows, descobri que, quando carreguei os preenchimentos (jd2xsx.dll chama & ftd2xx.dll) na pasta Windows/System32, isso resolveu os problemas. Em seguida, tive um problema com o meu mais recente fd2xx.dll tem a ver com parâmetros, e é por isso que tive que carregar a versão mais antiga desta DLL. Terei que disparar isso mais tarde.

Nota: O jd2xsx.dll chama o ftd2xx.dll, portanto, basta definir o caminho para o jd2xx.dll pode não funcionar.

Estou usando o Mac OS X Yosemite e o NetBeans 8.02, recebi o mesmo erro e a solução simples que encontrei é acima, isso é útil quando você precisa incluir a biblioteca nativa no projeto. Então faça o próximo para o 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

Espero que possa ser útil para alguém. O link onde eu encontrei a solução está aqui:java.library.path - o que é e como usar

Eu tive o mesmo problema e o erro foi devido a uma renomeação da DLL. Pode acontecer que o nome da biblioteca também esteja escrito em algum lugar dentro da DLL. Quando coloquei de volta seu nome original, pude carregar usando System.loadLibrary

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;





    }


}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top