سؤال

كيف يمكنني تحميل ملف dll مخصص في تطبيق الويب الخاص بي؟حاولت اتباع الطرق لكنها فشلت.

  • نسخ كافة ملفات dll المطلوبة في system32 مجلد وحاول تحميل واحد منهم في Servlet البناء System.loadLibrary
  • تم نسخ ملفات dll المطلوبة في tomcat_home/shared/lib و tomcat_home/common/lib
  • كل هذه dlls موجودة WEB-INF/lib من تطبيق الويب
هل كانت مفيدة؟

المحلول

من أجل System.loadLibrary() لكي تعمل، يجب أن تكون المكتبة (في نظام التشغيل Windows، DLL) في دليل في مكان ما على جهازك PATH أو على المسار المذكور في java.library.path خاصية النظام (حتى تتمكن من تشغيل Java مثل java -Djava.library.path=/path/to/dir).

بالإضافة إلى ذلك، ل loadLibrary(), ، يمكنك تحديد الاسم الأساسي للمكتبة، دون الامتداد .dll في نهايةالمطاف.وذلك ل /path/to/something.dll, ، سوف تستخدم فقط System.loadLibrary("something").

تحتاج أيضًا إلى إلقاء نظرة على الدقة UnsatisfiedLinkError الذي تحصل عليه.إذا قيل شيئا مثل:

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

ثم لا يمكن العثور على foo مكتبة (foo.dll) في جهازك PATH أو java.library.path.إذا قيل شيئا مثل:

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

إذن هناك خطأ ما في المكتبة نفسها، بمعنى أن Java غير قادرة على تعيين وظيفة Java أصلية في تطبيقك إلى نظيرتها الأصلية الفعلية.

في البداية، أود أن أضع بعض التسجيلات حولك System.loadLibrary() اتصل لمعرفة ما إذا كان ذلك سيتم تنفيذه بشكل صحيح.إذا طرح استثناءً أو لم يكن في مسار التعليمات البرمجية الذي تم تنفيذه بالفعل، فستحصل دائمًا على النوع الأخير من UnsatisfiedLinkError وأوضح أعلاه.

كملاحظة جانبية، يضع معظم الناس أسمائهم loadLibrary() يستدعي كتلة مُهيئ ثابتة في الفصل باستخدام الطرق الأصلية، للتأكد من تنفيذها دائمًا مرة واحدة بالضبط:

class Foo {

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

    public Foo() {
    }

}

نصائح أخرى

لا يعد تغيير متغير "java.library.path" في وقت التشغيل كافيًا لأنه تتم قراءته مرة واحدة فقط بواسطة JVM.يجب عليك إعادة ضبطه مثل:

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

من فضلكم اغتنموا الفرصة: تغيير مسار مكتبة جافا في وقت التشغيل.

ستقودك الإجابة الأصلية من آدم باتكين إلى الحل، ولكن إذا قمت بإعادة نشر تطبيق الويب الخاص بك (دون إعادة تشغيل حاوية الويب الخاصة بك)، فيجب أن تواجه الخطأ التالي:

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)

يحدث هذا لأن ClassLoader الذي قام في الأصل بتحميل مكتبة الارتباط الحيوي (DLL) الخاصة بك لا يزال يشير إلى ملف DLL هذا.ومع ذلك، فإن تطبيق الويب الخاص بك يعمل الآن باستخدام ClassLoader جديد، ونظرًا لأن نفس JVM قيد التشغيل ولن يسمح JVM بمرجعين إلى نفس DLL، فلا يمكنك إعادة تحميل هو - هي.وبالتالي، لا يستطيع تطبيق الويب الخاص بك الوصول إلى ملف DLL الحالي ولا يمكنه تحميل ملف جديد.لذا....انت عالق.

وثائق Tomcat ClassLoader يوضح سبب تشغيل تطبيق الويب المعاد تحميله في ClassLoader المعزول الجديد وكيف يمكنك التغلب على هذا القيد (على مستوى عالٍ جدًا).

الحل هو توسيع حل آدم باتكين قليلاً:

   package awesome;

   public class Foo {

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

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

    }

ثم قم بوضع جرة تحتوي على هذه الفئة المترجمة فقط في المجلد TOMCAT_HOME/lib.

الآن، داخل تطبيق الويب الخاص بك، كل ما عليك فعله هو إجبار Tomcat على الإشارة إلى هذا الفصل، وهو ما يمكن القيام به ببساطة كما يلي:

  Class.forName("awesome.Foo");

يجب الآن تحميل ملف DLL الخاص بك في أداة تحميل الفئة العامة، ويمكن الرجوع إليه من تطبيق الويب الخاص بك حتى بعد إعادة نشره.

منطقي؟

يمكن العثور على نسخة مرجعية للعمل على كود جوجل، static-dll-bootstrapper .

يمكنك استخدام System.load() لتوفير المسار المطلق وهو ما تريده، بدلاً من ملف في مجلد المكتبة القياسية لنظام التشغيل المعني.

إذا كنت تريد التطبيقات الأصلية الموجودة بالفعل، استخدم System.loadLibrary(String filename).إذا كنت ترغب في توفير الخاص بك فمن الأفضل أن تستخدم Load() .

يجب أن تكون أيضًا قادرًا على الاستخدام loadLibrary مع ال java.library.path تعيين بشكل صحيح.يرى ClassLoader.java لمصدر التنفيذ الذي يوضح كلا المسارين قيد التحقق (OpenJDK)

في الحالة التي تكون فيها المشكلة هي أن System.loadLibrary لا يمكنه العثور على ملف DLL المعني، فإن أحد المفاهيم الخاطئة الشائعة (التي تعززها رسالة خطأ Java) هو أن خاصية النظام java.library.path هي الحل.إذا قمت بتعيين خاصية النظام java.library.path إلى الدليل الذي يوجد به ملف DLL الخاص بك، فسيقوم System.loadLibrary بالفعل بالعثور على ملف DLL الخاص بك.ومع ذلك، إذا كان ملف DLL الخاص بك يعتمد بدوره على مكتبات DLL أخرى، كما هو الحال غالبًا، فلن يتمكن java.library.path من المساعدة، لأن تحميل مكتبات DLL التابعة تتم إدارته بالكامل بواسطة نظام التشغيل، الذي لا يعرف شيئًا عن java.library. طريق.وبالتالي، فمن الأفضل دائمًا تجاوز java.library.path وإضافة دليل DLL الخاص بك إلى LD_LIBRARY_PATH (Linux)، أو DYLD_LIBRARY_PATH (MacOS)، أو Path (Windows) قبل بدء تشغيل JVM.

(ملحوظة:أنا أستخدم المصطلح "DLL" بالمعنى العام لـ DLL أو المكتبة المشتركة.)

إذا كنت بحاجة إلى تحميل ملف متعلق ببعض الأدلة التي تتواجد فيها بالفعل (كما هو الحال في الدليل الحالي)، فإليك الحل السهل:

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

بالنسبة لأولئك الذين يبحثون عن java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

كنت أواجه نفس الاستثناء.لقد جربت كل شيء والأشياء المهمة لإنجاحه هي:

  1. الإصدار الصحيح من pdf lib.jar (في حالتي، كان هناك إصدار خاطئ من jar تم الاحتفاظ به في وقت تشغيل الخادم)
  2. قم بإنشاء مجلد واحتفظ بجرة pdflib فيه وأضف المجلد في متغير PATH الخاص بك

عملت مع القط 6.

المسكين أنا !قضيت يومًا كاملاً خلف هذا. أكتبه هنا إذا كان أي شخص يكرر هذه المشكلة.

كنت أحاول التحميل كما اقترح آدم ولكن بعد ذلك تم اكتشاف استثناء AMD64 مقابل IA 32. إذا كان على أي حال بعد العمل وفقًا لمراجعة Adam (بلا شك أفضل اختيار)، فحاول الحصول على إصدار 64 بت من أحدث إصدار من jre. تأكد إصدار JRE وJDK الخاص بك هو 64 بت وقد قمت بإضافته بشكل صحيح إلى مسار الفصل الخاص بك.

مثال العمل الخاص بي يذهب هنا:خطأ في الارتباط غير الإحصائي

  1. إذا كنت تعتقد أنك أضفت مسار lib الأصلي إلى %PATH%، فاختبر نفسك مرة أخرى عن طريق:

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

يجب أن يُظهر لك فعليًا ما إذا كان ملف dll الخاص بك موجودًا على %PATH%

  1. قم بإعادة تشغيل IDE Idea، نعم، يبدو أنها تعمل بالنسبة لي بعد أن قمت بإعداد متغير env بإضافته إلى %PATH%

بالنسبة لنظام التشغيل Windows، وجدت أنه عندما قمت بتحميل الملفات (مكالمات jd2xsx.dll & ftd2xx.dll) في المجلد windowws/system32، أدى هذا إلى حل المشكلات.ثم واجهت مشكلة مع ملف fd2xx.dll الأحدث الخاص بي والمتعلق بالمعلمات ولهذا السبب اضطررت إلى تحميل الإصدار الأقدم من ملف dll هذا.سأضطر إلى توضيح هذا لاحقًا.

ملحوظة:يقوم jd2xsx.dll باستدعاء ftd2xx.dll لذا قد لا ينجح تعيين المسار لـ jd2xx.dll.

أنا أستخدم نظام التشغيل Mac OS X Yosemite وNetbeans 8.02، وحصلت على نفس الخطأ والحل البسيط الذي وجدته هو كما هو مذكور أعلاه، وهذا مفيد عندما تحتاج إلى تضمين مكتبة أصلية في المشروع.لذا قم بما يلي لـ 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

آمل أن تكون مفيدة لشخص ما.الرابط الذي وجدت فيه الحل هنا:java.library.path – ما هو وكيفية استخدامه

واجهت نفس المشكلة وكان الخطأ بسبب إعادة تسمية ملف dll.من الممكن أن يكون اسم المكتبة مكتوبًا أيضًا في مكان ما داخل ملف dll.عندما أعدت اسمه الأصلي تمكنت من التحميل باستخدام 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;





    }


}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top