通过JNI从Applet调用DLL

时间:2009-11-11 06:20:55

标签: java applet java-native-interface

我有一个“概念证明”的作品,跨越了一些不熟悉的领域。 我的任务是将EFTPOS计算机连接到在我们的Intranet上的浏览器中作为applet运行的应用程序。

我暂时忽略了EFTPOS dll,并用我选择的语言(Delphi)创建了一个简单的JNI修饰DLL,它只是将字符串记录到c:\中的文本文件中,我可以从本地成功调用它Java应用程序。

然而,当我创建一个小程序来做同样的事情时,将其编译成.JAR,签署JAR&尝试在网页上通过Javascript调用applet中的方法失败。

我正在与之合作的高级Java人员认为不可能让这个工作起作用,因为允许applet执行此操作本身就是“邪恶的”。

您可以在java.policy文件中放入一个条目以允许loadLibrary。以及所有的许可和我在这些行中尝试了大量的变体,但无法在Java控制台中产生以下错误跟踪:

java.lang.ExceptionInInitializerError
  at app.TestApplet.LogAString(Unknown Source)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Unknown Source)
  at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Unknown Source)
  at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
  at sun.plugin.com.MethodDispatcher.invoke(Unknown Source)
  at sun.plugin.com.DispatchImpl.invokeImpl(Unknown Source)
  at sun.plugin.com.DispatchImpl$1.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  at sun.plugin.com.DispatchImpl.invoke(Unknown Source)
Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission loadLibrary.DLoggerImpl)
  at java.security.AccessControlContext.checkPermission(Unknown Source)
  at java.security.AccessController.checkPermission(Unknown Source)
  at java.lang.SecurityManager.checkPermission(Unknown Source)
  at java.lang.SecurityManager.checkLink(Unknown Source)
  at java.lang.Runtime.loadLibrary0(Unknown Source)
  at java.lang.System.loadLibrary(Unknown Source)
  at app.DLogger.<clinit>(Unknown Source)
  ... 16 more
java.lang.Exception: java.lang.ExceptionInInitializerError
  at sun.plugin.com.DispatchImpl.invokeImpl(Unknown Source)
  at sun.plugin.com.DispatchImpl$1.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  at sun.plugin.com.DispatchImpl.invoke(Unknown Source)

关键行似乎是“由:java.security.AccessControlException:access denied(java.lang.RuntimePermission loadLibrary.DLoggerImpl)”,这意味着权限问题。可能是我得到的策略文件错误 - 或签名错误 - 或类似的东西,或者由于安全风险,Java可能是硬连线不允许Applet的那种权限。

我的问题是我在浪费时间吗?可以做到吗?如果是这样,怎么样?

感谢您的期待

麦克

3 个答案:

答案 0 :(得分:14)

你绝对可以做到这一点。我有一个正在生产的工作小程序正是这样做的。即使您的applet已签名,您仍然需要使用Access Controller来访问dll,您不能只调用“loadlibrary”。您可以将其添加到Java策略文件中,但由于1,建议不要这样做。您可能无权访问用户java配置。 2.即使这是为了您自己的公司使用,管理策略文件也很痛苦,因为用户将下载一些JRE并且您的策略文件被覆盖或被忽略。

最好的办法是签署你的jar,确保将你的加载库代码包装在这样的特权代码块中。

try
{
    AccessController.doPrivileged(new PrivilegedAction()
    {
        public Object run()
        {
            try
            {
                // privileged code goes here, for example:
                System.load("C:/Program Files/.../Mydll.dll");
                return null; // nothing to return
            }
            catch (Exception e)
            {
                System.out.println("Unable to load Mydll");
                return null;
            }
        }
     });
}
catch (Exception e)
{
    System.out.println("Unable to load Mydll");
}

您也可以使用System.loadlibrary(mydll.dll),但是您必须在Windows中的路径上安装dll文件夹,以便applet可以找到它。

如果你需要一些源代码来调用JNI函数,请告诉我我也可以抓住它。

答案 1 :(得分:0)

我唯一可以建议的是查看该区域的源代码,并尝试解密,如果由于缺少权限而不允许或因为根本不允许这样做。不幸的是,你没有行号,所以这会让它变得有点棘手。

答案 2 :(得分:0)

我很确定您无法从Applet加载本机库,除非它已“签名”,然后用户将获得允许或禁止的接受对话框。也就是说,假设您可以在applet中完成JNI ...从未尝试过。

祝你好运。