如果jar文件>达到一定大小,则Applet无法在Windows 7上加载Java 1.7

2022-09-04 23:28:32

我们有一个相当复杂的签名小程序,自从我们几年前开发它以来,它一直工作得很好。它可以在我们关心的所有操作系统/浏览器配置上运行良好,适用于Java 1.5和1.6。

它不适用于Windows 7或Vista上任何浏览器中的Java 1.7。我们已经看到它在Windows XP上工作。此小程序在 Apache 使用mod_proxy连接到 Tomcat 6 的站点中运行。

这就是全部的背景信息,因为我已将问题简化为一个非常简单的未签名小程序:

package myapplet;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;

public class MyApplet extends Applet {
    private static final long    serialVersionUID    = 1L;

    public void paint(Graphics g) {
        g.drawRect(0, 0, 250, 100);
        g.setColor(Color.blue);
        g.drawString("Look at me, I'm a Java Applet!", 10, 50);
    }
}

如果将此小程序类放入一个 jar 文件中,另一个文件占用 jar 文件的总(压缩)大小超过约 18KB,则当由本地运行的 Tomcat 6(或 Apache 2.2)提供服务时,小程序不会加载。

我通过向jar文件添加文本文件并更改文本文件的大小来尝试。我通过向文本文件添加一个字符,使它从工作到不工作。

查看带有跟踪的控制台日志在尝试下载 jar 文件的位置挂起。这是我认为悬而未决的线程:

"thread applet-com.bright.assetbank.clientsideedit.myapplet.MyApplet-1" prio=4 tid=0x048d8c00 nid=0x19b8 runnable [0x0700d000]
    java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    - locked <0x29fd75b0> (a java.io.BufferedInputStream)
    at sun.net.www.MeteredStream.read(Unknown Source)
    - locked <0x29fd75d0> (a sun.net.www.http.KeepAliveStream)
    at java.io.FilterInputStream.read(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    - locked <0x29fd7630> (a java.io.BufferedInputStream)
    at java.io.FilterInputStream.read(Unknown Source)
    at sun.plugin.PluginURLJarFileCallBack.downloadJAR(Unknown Source)
    at sun.plugin.PluginURLJarFileCallBack.access$000(Unknown Source)
    at sun.plugin.PluginURLJarFileCallBack$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.plugin.PluginURLJarFileCallBack.retrieve(Unknown Source)
    at sun.net.www.protocol.jar.URLJarFile.retrieve(Unknown Source)
    at sun.net.www.protocol.jar.URLJarFile.getJarFile(Unknown Source)
    at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
    at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
    at sun.plugin.net.protocol.jar.CachedJarURLConnection.connect(Unknown Source)
    at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFileInternal(Unknown Source)
    - locked <0x29f2a938> (a sun.plugin.net.protocol.jar.CachedJarURLConnection)
    at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFile(Unknown Source)
    - locked <0x29f2a938> (a sun.plugin.net.protocol.jar.CachedJarURLConnection)
    at com.sun.deploy.security.DeployURLClassPath$JarLoader.getJarFile(Unknown Source)
    at com.sun.deploy.security.DeployURLClassPath$JarLoader.access$1000(Unknown Source)
    at com.sun.deploy.security.DeployURLClassPath$JarLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.deploy.security.DeployURLClassPath$JarLoader.ensureOpen(Unknown Source)
    at com.sun.deploy.security.DeployURLClassPath$JarLoader.<init>(Unknown Source)
    at com.sun.deploy.security.DeployURLClassPath$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
    at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
    - locked <0x29dc7e98> (a com.sun.deploy.security.DeployURLClassPath)
    at com.sun.deploy.security.DeployURLClassPath.getResource(Unknown Source)
    at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.plugin2.applet.Plugin2ClassLoader.findClassHelper(Unknown Source)
    at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
    - locked <0x29dc7ed8> (a sun.plugin2.applet.Applet2ClassLoader)
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
    - locked <0x29dc7f78> (a sun.plugin2.applet.Applet2ClassLoader)
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
    - locked <0x29dc7f78> (a sun.plugin2.applet.Applet2ClassLoader)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
    at sun.plugin2.applet.Plugin2Manager.initAppletAdapter(Unknown Source)
    at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

以下是 Java 控制台中的最后 4 行:

network: Cache entry not found [url: http://localhost/editor.jar, version: null]
network: Connecting http://localhost/editor.jar with proxy=DIRECT
network: Connecting http://localhost:80/ with proxy=DIRECT
network: Connecting http://localhost/editor.jar with cookie "csrftoken=523154b2e73a76b6f2088464bd4df4f7"

一些附加信息:

  • 在Windows Vista上,在浏览器中运行Java 7,如果我取消选中“启用黑名单吊销检查”,我们的主小程序(由Apache->mod_proxy->tomcat提供)将加载。如果选中此选项,则不会加载。取消选中此选项对Windows 7没有影响(即不使其工作)。
  • 我尝试在Tomcat(本地),Apache(本地)和Apache(在我通过Internet访问的远程服务器上)托管我的测试小程序。对于每个,都有一个jar文件的大小,上面小程序不会加载 - 但是,这个大小在Web服务器之间有所不同。例如,在远程服务器上,jar文件可能要大得多 - 它必须超过~1MB才能加载。

当尝试加载在Windows 7或Vista上的浏览器中运行的Java 7的小程序时,是否有其他人看到过这种行为?有解决方案吗?

有关如何重现此问题的分步说明:

  • 将上面的代码复制到一个名为MyApplet的文件中.java该文件位于名为myapplet的目录中
  • 编译代码,即javac MyApplet.java
  • 创建一个 jar 文件:cd 到 myapplet 的父目录,然后键入 jar -cvf 编辑器.jar myapplet
  • 创建一个简单的 HTML 页面来显示小程序。

例如:

<html>  
    <body>
        <applet code="myapplet.MyApplet" name="MyApplet" width="300" height="300" archive= "editor.jar" ></applet>
    </body>
</html>
  • 将此HTML文件和jar文件放入同一目录中,并从Web服务器(例如Apache或Tomcat)提供服务。
  • 在 Windows 7 操作系统上的 Chrome 或 IE 中访问此 HTML 页面。小程序将加载正常!
  • 重复上述步骤,但这次在创建jar文件之前,将一个小文件(例如<2KB)放入myapplet目录(MyApplet.class旁边)。这也应该有效。
  • 重复上述步骤,但这次在创建 jar 文件之前,将一个大图像(例如 >100KB)放入 myapplet 目录(MyApplet.class旁边)。jar 文件现在将非常大。这不起作用,即小程序不会加载。如果是这样,并且您使用的是Windows 7,那么请告诉我。在测试时,不要忘记小程序是缓存的,因此在java控制台中按x键刷新类加载器缓存,按f5刷新浏览器。

答案 1

Java bug 数据库中 bug 7183450的解决方法修复了此问题,即添加

-Djava.net.preferIPv4Stack=true 

到 JVM 参数。

例如,要运行我的测试小程序(请参阅上面问题中的示例):

<html>  
    <body>
        <applet code="myapplet.MyApplet" name="MyApplet" width="300" height="300" archive= "editor.jar" >
        <param name="java_arguments" value="-Djava.net.preferIPv4Stack=true">
    </applet>
    </body>
</html>

这可能是因为托管我们小程序的远程服务器目前不允许IPv6通信通过其防火墙。

有趣的是,即使在运行Java 1.7_05时,我们的一些Windows 7计算机仍然无法正常工作,但是当升级到Java 1.7_06(现在可用)时,它确实可以正常工作(使用此解决方法)。


答案 2

推荐