Исключение UnsatisfiedLinkError при работе с dll и java jni4net

Я работал над чтением функции С# (dll) из java через jni4net, и в основной java мне удалось получить значение из функции dll, но теперь я создал один динамический веб-проект и попытался использовать те же функции в сервлете. Но теперь успешно загружается только файл dll, функция не вызывается успешно. Ниже то, что я пробовал до сих пор:

Мой сервлет:

public class LoginProcess extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        try {

            Bridge.setVerbose(true);
            Bridge.init();
            Console.WriteLine("Hello .NET world!\n");

            Bridge.LoadAndRegisterAssemblyFrom(new File("C:/Users/ashish.it/workspace/FinalJniWeb/WebContent/WEB-INF/lib/ADHelper.j4n.dll"));

        } catch (IOException e) {
            e.printStackTrace();
        }
        Enum output;
        output=ADHelper.Login("user", "pass");
        System.out.println(output);
    }
}

Единственная разница, когда я сделал это в core java, заключалась в том, что я не использовал полный путь, вместо этого я использовал только «lib/ADHelper.j4n.dll» для пути, но почему-то он не работал в сервлете, поэтому я изменил его на полный путь. В любом случае файл dll загружается успешно.

ADHelper.generated.cs

namespace ADHelper {
    public partial class ADHelper_ {

methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "Login", "Login2", "(Ljava/lang/String;Ljava/lang/String;)Lsystem/Enum;"));

  private static global::net.sf.jni4net.utils.JniHandle Login2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class, global::net.sf.jni4net.utils.JniLocalHandle UserName, global::net.sf.jni4net.utils.JniLocalHandle Password) {
            // (Ljava/lang/String;Ljava/lang/String;)Lsystem/Enum;
            // (LSystem/String;LSystem/String;)LADHelper/ADHelper+LoginResult;
            global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp);
            global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle);
            try {
            @__return = global::net.sf.jni4net.utils.Convertor.StrongC2Jp<global::ADHelper.ADHelper.LoginResult>(@__env, global::ADHelper.ADHelper.Login(global::net.sf.jni4net.utils.Convertor.StrongJ2CString(@__env, UserName), global::net.sf.jni4net.utils.Convertor.StrongJ2CString(@__env, Password)));
            }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);}
            return @__return;
        }
}

Подчеркивание было смешано с именем класса ADHelper, когда я запускал команду proxygen. в файле dll есть два класса с именами ADHelper и ADHelper

Функция Login() также была изменена на Login2(), но Login2() не распознается моим сервлетом, тогда как Login() распознается.

Сгенерированный класс Java ADHelper.java

package adhelper;

@net.sf.jni4net.attributes.ClrType
public class ADHelper extends system.Object { 

private static system.Type staticType;

    protected ADHelper(net.sf.jni4net.inj.INJEnv __env, long __handle) {
            super(__env, __handle);
    }

    @net.sf.jni4net.attributes.ClrConstructor("()V")
    public ADHelper() {
            super(((net.sf.jni4net.inj.INJEnv)(null)), 0);
        adhelper.ADHelper.__ctorADHelper0(this);
    }

@net.sf.jni4net.attributes.ClrMethod("(LSystem/String;LSystem/String;)LADHelper/ADHelper+LoginResult;")
    public native static system.Enum Login(java.lang.String UserName, java.lang.String Password);

 public static system.Type typeof() {
        return adhelper.ADHelper.staticType;
    }

 private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) {
        adhelper.ADHelper.staticType = staticType;
    }
}

Все сопоставления правильные, но моя функция входа в систему дает unsatisfiedLinkError. Спасибо за терпение при чтении, пожалуйста, дайте решение моей проблемы.

На консоли возникает следующая ошибка:

*All Dll file loaded message*
Jun 3, 2015 10:56:39 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet LoginProcess threw exception
java.lang.UnsatisfiedLinkError: adhelper.ADHelper.Login(Ljava/lang/String;Ljava/lang/String;)Lsystem/Enum;
    at adhelper.ADHelper.Login(Native Method)
    at com.karvy.login.LoginProcess.doGet(LoginProcess.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

person XeeMez AsHu    schedule 03.06.2015    source источник


Ответы (3)


Возможно, вы можете проверить загрузчик классов, загружающий ваш файл из разных загрузчиков классов в другом контексте.

person Priya Aanchal    schedule 08.06.2015
comment
Я заставляю dll загружаться из загрузчика классов веб-контекста, но никаких изменений нет. - person XeeMez AsHu; 08.06.2015

Я считал, что это проблема с загрузчиком классов, которой не было, когда я позже подавил свои файлы для загрузки из того же загрузчика классов.

Дальнейшее изучение показало, что путь, который я указывал, был прямым путем к файлу в каталоге и не указывал на то же направление, что и файл в области контекста сервлета. Для этого мне пришлось создать servlet context object, и после этого был вызван метод getResuorce, чтобы я мог получить свой файл и быть готовым к использованию.

Вот код для получения файла из области контекста сервлета:

ServletContext context = getServletContext();
String realPath = context.getRealPath("/WEB-INF/lib/ADHelper.j4n.dll");
File file = new File(realPath);

Спасибо @surabhi-rai за вашу поддержку. Я разместил этот ответ, если в будущем кто-то столкнется с этой проблемой, может прийти сюда. Спасибо и добро пожаловать. ☻

person XeeMez AsHu    schedule 10.06.2015

Получите ссылку на файл через объект контекста сервлета, а затем вызовите для него метод getResource.

Прямо сейчас вы указываете на локальный каталог, который не находится в области контекста сервлета.

person Surabhi Rai    schedule 10.06.2015