java 通过 JNI 从 Applet 调用 DLL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1713403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:41:38  来源:igfitidea点击:

Calling a DLL from an Applet via JNI

javaappletjava-native-interface

提问by mcottle

I have a "proof of concept" piece of work that crosses over into some unfamiliar territory. I'm tasked with connecting an EFTPOS machine to an application running as an applet in a browser on our intranet.

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

I've ignored the EFTPOS dll for the moment and created a simple JNI decorated DLL in my language of choice (Delphi) that just logs a string to a text file in c:\ and I can call it successfully from a local Java application.

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

However, when I create an applet to do the same thing, compile it into a .JAR, sign the JAR & try to call the method in the applet via Javascript on a web page it fails.

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

A senior Java guy I'm working with doesn't think it will be possible to get this to work because it's inherently "evil" to allow an applet to do this.

与我一起工作的一位资深 Java 人员认为不可能让它工作,因为允许小程序执行此操作本质上是“邪恶的”。

There is an entry you can put in a java.policy file to allow loadLibrary. as well as allPermission & I've tried a whole host of variations along those lines all to no avail producing the following error trace in the Java Console:

您可以在 java.policy 文件中放入一个条目以允许 loadLibrary。以及 allPermission & 我已经尝试了沿这些方向的一大堆变体,但都无济于事,在 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.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.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  at sun.plugin.com.DispatchImpl.invoke(Unknown Source)

The key line seems to be "Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission loadLibrary.DLoggerImpl)" which implies a permissions problem. It could be that I'm getting the policy file wrong - or the signing wrong - or stuff like that or it could be that Java is hardwired to not allow those sort of permissions for an Applet because of the security risk.

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

My question is am I wasting my time? Can it be done & if so, how?

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

Thanks in anticipation

感谢期待

Mike

麦克风

回答by Keibosh

You can definitely accomplish this. I have a working applet in production that does exactly this. Even if your applet is signed, you still need to use the Access Controller to access the dll, you cannot just call "loadlibrary". You can add this to the Java policy file however this is not recommended due to 1. You probably do not have access to the users java configuration. 2. Even if this is for your own company use, managing the policy file is a pain as users will download some JRE and your policy file is either overwritten or ignored.

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

You best bet is to sign your jar, making sure to wrap your load library code in a privileged block of code like this.

您最好的办法是对您的 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");
}

You can Also use System.loadlibrary(mydll.dll) but you have to have the dll folder on the path in windows so the applet can find it.

您也可以使用 System.loadlibrary(mydll.dll) 但您必须在 windows 路径上有 dll 文件夹,以便小程序可以找到它。

If you need some source samples for calling the JNI functions let me know I can grab that as well.

如果您需要一些用于调用 JNI 函数的源示例,请告诉我我也可以获取。

回答by Michael Wiles

The only thing I can suggest is taking a look at the source code for that area and trying to decipher if it is not allowing because of lack of permission or because that is not allowed at all. You don't have line numbers unfortunately, so that makes it a little more tricky.

我唯一可以建议的是查看该区域的源代码,并尝试破译它是否由于缺乏许可或根本不允许而不允许。不幸的是,您没有行号,因此这使它变得更加棘手。

回答by cjstehno

I am pretty sure you cannot load a native library from an Applet unless it is "signed", and then the user will get an acceptance dialog to allow or disallow. That is, assuming you can do JNI at all in an applet... never tried that.

我很确定你不能从 Applet 加载本地库,除非它被“签名”,然后用户会得到一个接受对话框来允许或不允许。也就是说,假设您完全可以在小程序中执行 JNI ……从未尝试过。

Good luck.

祝你好运。