【问题标题】:Class not found when using SwingUtilities.invokeLater in OSGi Bundle在 OSGi Bundle 中使用 SwingUtilities.invokeLater 时找不到类
【发布时间】:2012-05-15 14:20:51
【问题描述】:

(编辑:问题已解决 - 详情见最后)

我想在 OSGi Bundle 中创建一个带有 WindowAdapter 的 Swing JFrame。当我使用SwingUtilities.invokeLater 执行此操作时,找不到WindowAdapter 类。没有invokeLater 它可以工作。

我需要做什么才能在使用invokeLater 时找到WindowAdapterinvokeLater 在 OSGi 环境中是否不合适?

详情:

我使用自定义启动器启动 Apache Felix 框架实例,安装捆绑包并启动它。我的 bundle 的 start 方法是这样的:

public void start(BundleContext arg0) throws Exception {
    myFrame = new MyFrame();
    myFrame.open();
}

这是 MyFrame 类:

public class MyFrame {
    JFrame mainFrame;

    public void open() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                openImpl();
            }
        });
        // If called like this it works:
        // openImpl();
    }

    public void openImpl() {
        mainFrame = new JFrame("Title");
        mainFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        WindowAdapter wa = new WindowAdapter() {
        };
        mainFrame.addWindowListener(wa);
        mainFrame.setSize(800, 600);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible(true);
    }
}

这是我的捆绑清单:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_03-b05 (Oracle Corporation)
Built-By: Rainer Schwarze
Bundle-Name: DummyBdl
Bundle-Description: Dummy Bundle
Bundle-Vendor: admaDIC
Bundle-Version: 0.0.1
Bundle-Activator: dummybdl.Activator
Import-Package: org.osgi.framework, javax.swing
Export-Package: dummybdl.api
Export-Service: dummybdl.Provider

这是我得到的堆栈跟踪:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1432)
    at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72)
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at dummybdl.MyFrame.openImpl(MyFrame.java:24)
    at dummybdl.MyFrame$1.run(MyFrame.java:16)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:675)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

作为一个 OSGi 新手,我尝试了几件事来修复它,但到目前为止找不到解决方案。那么为什么不在 StackOverflow 上提出我的第一个问题 :-)

编辑:

调试了半个小时发现问题完全是我的问题: 我的代码在 EDT 中调用 openImpl 之前停止了 OSGi 框架。

因此,Apache Felix 框架将 BundleWiringImpl 实例(参见堆栈跟踪)标记为已释放。当我的 openImpl 在 EDT 中被调用时,BundleWiringImpl.getClassLoader 返回 null,因为它被标记为已处置。最终这会导致 NPE。 (我应该采取额外的步骤来发布我的 Felix 加载程序的 50 行,这可能会使错误变得明显。)

【问题讨论】:

  • 如果您的代码是准确的,那么 MyFrame.java:24 行是“new JFrame()”,因此无法加载的类可能是 javax.swing.JFrame。我真的被这件事难住了。想了很久……
  • 如果我有 write jar 版本,那么 BundleWiringImpl 的第 1432 行是这样的:grepcode.com/file/repo1.maven.org/maven2/org.apache.felix/…,这意味着 getClassLoader() 返回 null 或 m_revision 为 null。

标签: java swing osgi event-dispatch-thread invokelater


【解决方案1】:

答案您尝试使用的WindowAdapter 类位于java.awt.event,但您没有导入该包。 编辑:这似乎没有来解决这个问题(见 cmets),但下面的背景故事仍然存在。

背景故事 您的清单看起来是手工制作的,我建议您不要这样做(您会犯错误,而且要使清单保持良好同步很麻烦)。如果您使用的是 Eclipse,请查看 bndtools,或者在任何其他环境中查看 bnd

【讨论】:

  • 当我将 java.awt.event 添加到 Import-Package 时,我得到:org.osgi.framework.BundleException: Importing java.* packages not allowed: java.awt.event
  • 哦,好点,我完全错过了。尽管如此,我仍然坚持我的观点,即您不应该手动构建清单,而是让工具来完成。我会为此更新我的答案。
  • 我试过 bndtools 看看它是否有一些我的新手理解没有涵盖的魔法。但是相关的 MANIFEST 条目是相同的,并且仍然抛出异常。与此同时,我发现了一篇有趣的文章,可以解决这个问题。我会在几个小时后有一点空闲时间并发布更新时阅读。
【解决方案2】:

我的代码在 EDT 中调用 openImpl 之前停止了 OSGi 框架。

没有invokeLater openImpl 在我的其他代码关闭OSGi 框架之前立即被调用。对于invokeLater,对openImpl 的调用被安排在稍后发生,在“稍后”发生之前,我的代码将关闭OSGi 框架。

在这种情况下,Apache Felix 框架将BundleWiringImpl 实例(参见堆栈跟踪)标记为已释放。当我的 openImpl 在 EDT 中被调用时,BundleWiringImpl.getClassLoader 返回 null,因为它被标记为已处置。最终这会导致 NPE。

【讨论】:

  • (发现自我回答是可以接受的,并决定将我的问题移出未回答的池......)
【解决方案3】:

堆栈跟踪包含一些安全检查“ProtectionDomain,..doIntersectionPrivilege”。 您是否尝试过禁用 SecurityManager。您可以使用以下 VM 选项禁用:

-Djava.security.manager=

请看这里: How to disable Java security manager?

【讨论】:

  • 我以-Djava.security.manager -Djava.security.policy=java.policy 开始我的应用程序并将grant { permission java.security.AllPermission; }; 放入策略文件中。仍然是相同的堆栈跟踪。如果没有策略文件参数,我会得到java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "createSecurityManager")。嗯。
猜你喜欢
  • 2015-07-20
  • 2011-06-18
  • 2013-01-08
  • 1970-01-01
  • 2012-04-17
  • 2011-09-21
  • 2019-01-03
  • 2015-12-30
  • 2012-08-26
相关资源
最近更新 更多