【问题标题】:Classloading conflict with two eclipse plugins与两个 Eclipse 插件的类加载冲突
【发布时间】:2012-03-14 21:26:19
【问题描述】:

以下情况:

在工作中,我们有一个自己的插件,它扩展了一些 JDT 功能并为我们自己的框架构建了一些辅助函数。到现在为止还挺好。

插件包括以下类:

public class MoxLogFactory extends org.apache.commons.logging.LogFactory {   
    ...
}

(我省略了具体的实现,因为它真的很全面)

现在我将 WindowBuilder-Plugin 添加到我的 Eclipse 安装中。我可以使用包含的向导创建新项目和类。但主要功能 - 编辑本人 - 不起作用。结果表明,WindowBuilder 试图从我们的插件中加载类“MoxLogFactory”!我附上了打开编辑器时出现的堆栈跟踪:

java.lang.ClassNotFoundException: org.dreamox.moxanos.log.MoxLogFactory
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:1261)
at org.apache.commons.logging.LogFactory$2.run(LogFactory.java:1065)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.commons.logging.LogFactory.newFactory(LogFactory.java:1062)
at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:497)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:704)
at org.apache.commons.digester.Digester.<init>(Digester.java:340)
at org.eclipse.wb.internal.core.model.description.helpers.ComponentDescriptionHelper.getDescription0(ComponentDescriptionHelper.java:375)
at org.eclipse.wb.internal.core.model.description.helpers.ComponentDescriptionHelper.getDescription0(ComponentDescriptionHelper.java:289)
at org.eclipse.wb.internal.core.model.description.helpers.ComponentDescriptionHelper.getDescription(ComponentDescriptionHelper.java:258)
at org.eclipse.wb.internal.core.model.JavaInfoUtils.createJavaInfo(JavaInfoUtils.java:386)
at org.eclipse.wb.internal.rcp.parser.ParseFactory.getRootContext(ParseFactory.java:184)
at org.eclipse.wb.internal.core.parser.JavaInfoParser.prepareParseContext(JavaInfoParser.java:1185)
at org.eclipse.wb.internal.core.parser.JavaInfoParser.parse(JavaInfoParser.java:244)
at org.eclipse.wb.internal.core.parser.JavaInfoParser.access$9(JavaInfoParser.java:240)
at org.eclipse.wb.internal.core.parser.JavaInfoParser$1.runObject(JavaInfoParser.java:153)
at org.eclipse.wb.internal.core.parser.JavaInfoParser$1.runObject(JavaInfoParser.java:1)
at org.eclipse.wb.internal.core.utils.execution.ExecutionUtils.runDesignTime(ExecutionUtils.java:153)
at org.eclipse.wb.internal.core.parser.JavaInfoParser.parse(JavaInfoParser.java:151)
at org.eclipse.wb.internal.core.editor.DesignPage.internal_refreshGEF(DesignPage.java:522)
at org.eclipse.wb.internal.core.editor.DesignPage.access$9(DesignPage.java:510)
at org.eclipse.wb.internal.core.editor.DesignPage$8$1.run(DesignPage.java:437)
at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:180)
at org.eclipse.ui.internal.UISynchronizer.syncExec(UISynchronizer.java:150)
at org.eclipse.swt.widgets.Display.syncExec(Display.java:4683)
at org.eclipse.wb.internal.core.editor.DesignPage$8.run(DesignPage.java:434)
at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
at org.eclipse.jface.dialogs.ProgressMonitorDialog.run(ProgressMonitorDialog.java:507)
at org.eclipse.wb.internal.core.editor.DesignPage.internal_refreshGEF_withProgress(DesignPage.java:453)
at org.eclipse.wb.internal.core.editor.DesignPage.internal_refreshGEF(DesignPage.java:403)
at org.eclipse.wb.internal.core.editor.UndoManager.refreshDesignerEditor(UndoManager.java:381)
at org.eclipse.wb.internal.core.editor.UndoManager.activate(UndoManager.java:90)
at org.eclipse.wb.internal.core.editor.DesignPage.handleActiveState_True(DesignPage.java:251)
at org.eclipse.wb.internal.core.editor.DesignPage.handleActiveState(DesignPage.java:229)
at org.eclipse.wb.internal.core.editor.multi.DefaultMultiMode.showPage(DefaultMultiMode.java:125)
at org.eclipse.wb.internal.core.editor.multi.DefaultMultiMode$1.widgetSelected(DefaultMultiMode.java:63)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:240)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1062)
at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:774)
at org.eclipse.swt.custom.CTabFolder.setSelection(CTabFolder.java:2746)
at org.eclipse.swt.custom.CTabFolder.onMouse(CTabFolder.java:1433)
at org.eclipse.swt.custom.CTabFolder$1.handleEvent(CTabFolder.java:257)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4165)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3754)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:999)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:893)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:85)
at org.eclipse.ui.internal.Workbench$4.run(Workbench.java:579)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:534)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:352)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:624)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:579)
at org.eclipse.equinox.launcher.Main.run(Main.java:1433)
at org.eclipse.equinox.launcher.Main.main(Main.java:1409)

我们的插件不导出任何东西,那么为什么 WindowBuilder 试图从中加载一个类?它从哪里获取加载此类的信息?如果我卸载我们的插件,WindowBuilder 可以正常工作,但我需要两个插件才能有效地工作。

我发现,在 MoxLogFactory 的一个静态方法中有一行

System.setProperty("org.apache.commons.logging.LogFactory","org.dreamox.moxanos.log.MoxLogFactory");

我认为每个插件都在沙箱中运行,所以这不是一个真正的问题,但是当我看到堆栈跟踪时,似乎这个系统属性是“eclipse 中的全局”。 MoxLogFactory 类也在我们的应用服务器框架中使用,因此需要此代码 - 插件使用框架本身来工作。

我不知道如何解决这个问题,如果有任何提示或想法,我将不胜感激。

【问题讨论】:

    标签: java eclipse plugins classloader


    【解决方案1】:

    这里有一些选项:

    • 删除 JVM 级别系统属性的静态初始化,仅在需要时将其替换为命令行选项

    • 在静态初始化程序中,通过向 ClassLoader 询问 org.eclipse.equinox.launcher.Main 类来测试 Eclipse 执行上下文,如果是这样,请不要设置 logfactory 属性

    【讨论】:

    • 感谢您的想法。命令行不太适合,但第二个听起来很有趣。我从正在运行的类路径中进行了简单的检查来尝试它,但它几乎是相同的想法!谢谢!
    【解决方案2】:

    系统属性属于 JVM,而不是类加载器。通过将您的记录器设置为系统属性,大概是为了自动加载它,您已经告诉整个系统使用它。当另一个插件加载并尝试初始化其日志记录(似乎也使用 Apache Commons Logging)时,它会读取 System 属性,尝试加载在其中找到的类,并立即失败,因为它无法查看您的插件。

    【讨论】:

    • 我明白了。并且没有任何“发布”我的日志记录类的可能性。 Buddy-classloading 不适合,因为我必须操作 WindowBuilder,这不是我想要的。
    猜你喜欢
    • 1970-01-01
    • 2011-03-10
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2015-01-28
    相关资源
    最近更新 更多