Java Applet - 不能从最终类继承 [英] Java Applet - Cannot inherit from final class

查看:33
本文介绍了Java Applet - 不能从最终类继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个 Java 小程序,它在大多数客户端环境中都可以正常工作,主要是 Windows 7,但最近我们也被要求支持 Ubuntu 客户端.

We have a java applet which is working OK in most client environments, primarily Windows 7, but recently we have been asked to support Ubuntu clients as well.

问题在于,当在 Ubuntu 客户端(运行 Firefox 和本机安装的IcedTEA"Java VM 1.7.0_75)上启动小程序时,我们会收到此异常:

The problem is that when the applet is fired up on the Ubuntu client (running Firefox and the natively installed "IcedTEA" Java VM 1.7.0_75) we get this exception:

java.lang.VerifyError: Cannot inherit from final class
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at net.sourceforge.jnlp.runtime.JNLPClassLoader.access$1701(JNLPClassLoader.java:103)
    at net.sourceforge.jnlp.runtime.JNLPClassLoader$5.run(JNLPClassLoader.java:1636)
    at net.sourceforge.jnlp.runtime.JNLPClassLoader$5.run(JNLPClassLoader.java:1634)
    at java.security.AccessController.doPrivileged(Native Method)
    at net.sourceforge.jnlp.runtime.JNLPClassLoader.findClass(JNLPClassLoader.java:1633)
    at net.sourceforge.jnlp.runtime.JNLPClassLoader.loadClassExt(JNLPClassLoader.java:1670)
    at net.sourceforge.jnlp.runtime.JNLPClassLoader.loadClass(JNLPClassLoader.java:1471)
    at com.renosci.Nlx.chartapplet.NlxBrowserJsEngine.<init>(NlxBrowserJsEngine.java:46)
    at com.renosci.Nlx.chartapplet.UtilityApplet.init(UtilityApplet.java:87)
    at sun.applet.AppletPanel.run(AppletPanel.java:436)
    at java.lang.Thread.run(Thread.java:745)

我们在 Windows 下没有得到这个异常(不可否认,不同的 JVM 构建以及我们在 Windows 上使用的Oracle 提供了 VM,而不是这个 IcedTea 版本).

We don't get this exception under Windows (admittedly, different JVM builds and of on Windows we are using the Oracle supplied VMs instead of this IcedTea version).

我理解异常的含义 - 并且在谷歌快速搜索中发现了多个 SO 问题,这些问题主要归结为构建路径与类路径不同的建议,例如在编译时基类不是最终的,但在运行时类加载器发现它是最终的.

I understand the meaning of the exception - and have a quick google search revealed multiple SO questions that mainly boiled down to the the suggestion that the build path is not the same as the class path, such that at compile time a base class was not final, but at runtime the classloader is finding it final.

但是,我不明白这是怎么回事:

However, I don't understand how that can be the case:

  • 抛出错误的类是从作为我们代码库一部分的抽象基类扩展而来的,并且根据我们的版本控制系统从未确定过

  • The class which is throwing the error is extending from an abstract base class that is part of our codebase, and according to our version control system has never been final

在我正在测试的目标机器上不可能有这个类的任何其他版本——事实上,我为这个测试创建了一个新的虚拟机并立即解决了问题

There is no possibility of there being any other versions of this class on the target machine that I am testing with - in fact I created a fresh VM for this test and got the problem straight away

我假设它正在抱怨 NlxBrowserJsEngine 的类,在调用 loadClass 之前立即运行 - 对吗?并且这个类的基类是它认为是最终的?

I am assuming that the class it is complaining about NlxBrowserJsEngine, running immediately before the call to loadClass - is that correct? And that the base class of this class is the one which it thinks is final?

为了完整性 - 这里是类的声明(这是异常抱怨的第 46 行)和它仅有的两个字段的声明:

For completeness - here is the declaration of the class (which is the line 46 that the exception complains about) and the declaration of the only two fields it has:

public class NlxBrowserJsEngine extends NlxJsEngine {  /* Line 46 */
    private JSObject windowObj;
    static private Object evalLock = new Object();

JSObject 是 netscape.javascript.JSObject,由 Java 浏览器插件提供.

JSObject is netscape.javascript.JSObject, provided by the Java browser plugin.

这里是基类的声明:

public abstract class NlxJsEngine {

感谢您的任何见解!

推荐答案

我最终找到了原因.

正如@immibis 的评论所指出的,异常发生在类初始化期间,而不是在构造实例期间.

As indicated by @immibis's comments, the exception was during class initialization, rather during construction of an instance.

类 NlxBrowserJsEngine 的一个方法调用另一个类的静态方法 - 这个类是从 netscape.javascript.JSObject 扩展而来的.

One of the methods of class NlxBrowserJsEngine calls a static method of another class - and this class extends from netscape.javascript.JSObject.

oracle 实现中 这个 JSObject 类没有被声明为 final,所以扩展它可以正常工作.

In the oracle implementation this JSObject class is not declared final, so extending it works fine.

IcedTea 实现,JSObject 是最终的.所以在IcedTea JVM Plugin中加载这个类时,会抛出异常.

In the IcedTea implementation, JSObject is final. Therefore when loading this class in the IcedTea JVM Plugin, an exception is thrown.

我不确定这种不兼容性是否是 IcedTea 实施者的疏忽,还是有意为之(可能是出于安全原因?).无论哪种方式,它都给我们带来了很大的问题.

I'm not sure if this incompatibility was an oversight on behalf of the IcedTea implementors, or perhaps done deliberately (due to security perhaps?). Either way it caused big problems for us.

通过大量重构本来可以克服这个问题,但是在我们的案例中,这被认为不值得,因此我们决定要求我们的用户安装 Oracle JVM.

Through extensive refactoring it would have been possible to overcome this, however in our case this was not considered worthwhile so we have decided to require our users to install the Oracle JVM.

这篇关于Java Applet - 不能从最终类继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆