【问题标题】:Classloader in Applet: Can't access filesApplet 中的类加载器:无法访问文件
【发布时间】:2023-03-12 22:04:01
【问题描述】:

我有一个使用反射来实例化保存在某个目录中的代码的应用程序:我创建了一个 URLClassLoader,然后使用提供的 URL 加载类;这很好用。我试图将应用程序移植到 Applet。为了加载文本文件和图像,我将代码从使用相对路径更改为使用 getResourceAsStream(),效果很好。然而,对于类加载器,我仍然有一个 I/O 异常(在我将代码更改为使用流之前,我也曾经使用过文本文件和图像来获取):

java.security.AccessControlException: access denied (java.io.FilePermission /.../... read)

要加载的类包含在 jar 文件中(与所有其他资源一样)。有什么方法可以使用getResourceAsStream() 之类的不调用安全异常的方法来加载类?请注意:我说的是从 java 代码中调用的类加载器,而不是加载小程序的类加载器。

编辑:有关文件/文件夹结构的更多详细信息:

我的小程序位于 a 包 a.MyApplet 中,它使用了一个类 a.aa.Loader,该类用于加载存储在另一个文件夹 b 中的类(因此在加载小程序时不会加载)。文件夹 b 包含许多目录 b.c_i,其中 c_i 是唯一目录。这些目录中的每一个都有属于包x.y.z的类,因此b的整体文件夹结构是b.c_i.x.y.z; z 包含要加载的文件。当我创建 jar 时,顶层如下所示([] 表示文件夹): [a],[b],[data],[images] where [a]={MyApplet,[aa],[aaa]等} 和 [b]={c_1,_c2,...} 其中 c_i={[x]}, [x]={[y]}, [y]={[z]} 最后是 [z ]={类.class}。希望符号不要太奇怪。

Edit2:更多细节。

澄清一下:我要加载的类是其他人的类,都放在一个单独的目录“DIR”中(它们不是项目的一部分,它们本身也不构成项目)。事实上,所有这些类名都是相同的,它们存储在“DIR”内的唯一目录中。我需要一次加载一个文件。换句话说,我想像对待任何其他资源一样对待类文件。

注意:我尝试了一个签名的小程序,它不再抛出一个安全异常,而是一个 IO 异常:它找不到文件。我检查了目录结构并尝试了许多变体,所有变体都具有相同的结果(它适用于我的本地计算机)。我不确定这是否真的是一个 IO 问题,还是仍然是一个安全问题。

【问题讨论】:

  • FilePermission 中的路径是否与其中一种资源相关?
  • @jtahlborn 是的,我只是将目录名替换为... jar文件的结构如下:[images] [data] [要加载的文件] [package]。要加载的文件在它们自己的目录中,实际的小程序代码在[package]中。一切都在 jar 文件中。
  • @AndrewThompson:但要加载的类位于 jar 文件中的目录中。为什么它与作为小程序的一部分加载的类不同?
  • @coderino 你签署你的小程序了吗?
  • @FrozenSpider 不,目前没有签名。我可以签,但不想签(我认为人们可能会因此而推迟)。但是,如果这是唯一的解决方案,我当然会这样做。

标签: java security applet classloader sandbox


【解决方案1】:

实际上,将项目保留为单独的对象范围是一种糟糕的色调,所以...

  • 您可以将所有项目打包到一个 jar 文件中。

  • 如果您将课程保留在服务器上只是因为整个 项目太大,你可以用 pack200 util 压缩它 对 Java Web Start 胖客户端小程序很有帮助

  • 我推荐使用 jnlp 小程序启动类型,因为它提供 DeployJava.js

  • 提供更多选择

附言

如果您真的坚持使用类加载器加载资源,请以小程序标准方式执行,我的意思是使用 Anchor 对象

例如创建类似的结构

  • |- 包装图片-
  • |imageA.png
  • |imageB.png
  • |Anchor.class
  • |SourceBound.class

SourceBound.java

public class SourceBound
{

  /**
    Conception only...
  **/
  public SourceBound(){}

  public ImageIcon getImageA()
  {
    ImageIcon icon;
    Image image;

    image=ImageIO.read(Anchor.class.getResourceAsStream("imageA.png"));
    icon=new ImageIcon(image);

    return icon;
  }
}

  • |封装测试
  • |Test.class

Test.java

public class Test
{

SourceBound sourceBound=new SourceBound();

Test()
{
  JButton button=new JButton();
  button.setIcon(sourceBound.getImageA());

}

}

祝你好运

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 2013-12-02
    相关资源
    最近更新 更多