2

问题:在 Windows 平台上本地运行时,Java 小程序无法加载位于其 jar 中的资源。如果同一个小程序是从 Web 服务器启动而不是在本地启动,或者如果它是在 linux 系统上本地启动,则它可以加载资源。在所有情况下,小程序都是使用小程序标签启动的。

重现步骤

1)在下面构建小程序类代码并创建一个包含以下内容的jar:

  • 测试Applet.class
  • 图标img.png
  • 测试.html
  • META-INF 文件夹(标准清单,一行:“Manifest-Version: 1.0”)

这是我使用的图像 png 文件的链接:http: //flexibleretirementplanner.com/java/java-test/iconimg.png

文件 test.html 有一行:

<h1>Text from test.html file</h1>

2) 在与 test.jar 相同的文件夹中创建 launch.html,如下所示:

<html><center><title>Test Applet</title><applet
archive  = "test.jar"
code     = "TestApplet.class"
name     = "Test Applet"
width    = "250"
height   = "150"
hspace   = "0"
vspace   = "0"
align    = "middle"
mayscript = "true"
></applet></center></html>

3)在与launch.html相同的本地文件夹中使用test.jar,单击launch.html

4) 请注意,对 imgicon.png 和 test.html 的 getResource() 调用均返回 null。

5) 将launch.html 和test.jar 上传到Web 服务器并加载launch.html 并注意找到资源。

测试Applet.java

import java.applet.AppletContext;
import java.io.IOException;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class TestApplet extends JApplet {
    public TestApplet() {
        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    public void init() {
        JPanel topPanel = new JPanel();
        JLabel iconLabel;
        URL url = TestApplet.class.getClassLoader().getResource("iconimg.png");
        if  (url != null)
            iconLabel = new JLabel(new ImageIcon(url));
        else
            iconLabel = new JLabel("getResource(iconimg.png)==null");
        topPanel.add(iconLabel);

        URL url2;
        url2 = TestApplet.class.getClassLoader().getResource("test.html");
        if (url2 == null) {
            JLabel errorLabel = new JLabel("getResource(test.html) == null");
            topPanel.add(errorLabel);
        } else {
            try {
                JEditorPane htmlPane = new JEditorPane(url2);
                topPanel.add(htmlPane);
            } catch (IOException ioe) {
                System.err.println("Error displaying " + url2);
            }
        }
        getContentPane().add(topPanel);
    }   
  private void jbInit() throws Exception { }
}
4

2 回答 2

3

Oracle 已决定修改 getDocumentBase()、getCodeBase() 和 getResource() 的行为,因为从 1.7.0_25 开始在 Windows 上的安全原因:http ://www.duckware.com/tech/java-security-clusterfuck.html

似乎有很多关于此更改的讨论,因为它破坏了一些重要的有效且安全的用例。

于 2013-10-04T11:15:48.573 回答
1

在进一步研究并发现这是一个仅限 Windows 的问题后,我称之为已回答。

几乎可以肯定这是一个 java 1.7.0.25 错误。该小程序可以在 Web 服务器上正常运行,并且在虚拟 Ubuntu 系统上本地也可以正常运行(在 Windows 上使用 VirtualBox)。希望我提交的错误报告对java人员有所帮助。

感谢您的回复。顺便说一句,正是 Joop 关于区分大小写的评论促使我测试一个 Linux 系统只是为了好玩。感谢那!

于 2013-07-10T22:39:53.557 回答