静态块被调用两次,也许是多个类加载器?

时间:2013-01-21 07:16:53

标签: java java-ee weblogic ejb-3.0 classloader

我有一个MDB EJB,里面有静态块。我在第一次运行应用程序时(即在部署时)使用静态块来初始化一些组件。 MDB EJB部署在除Admin_Server之外的单独服务器(My_Server)上。

问题是静态块被调用两次!

  • 第一次:在部署MDB EJB之后(tageted到My_Server)。
  • 第二次:在JMS队列(与MDB关联)之后收到一条消息。

另外,我打印了服务器名称和pid,它们在两者中都是相同的:

System.out.println("server name: " + System.getProperty("weblogic.Name"));
System.out.println("pid: " + ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);

我也注意到一些奇怪的行为。基本上,我附上一个Shutdown Hook(从静态块内部),在关闭应用程序时向我发送电子邮件。

  • 我在关闭My_Server后收到通知。
  • 我关闭Admin_Server后也收到了通知。

我该如何解决这个问题?


一些额外信息:

Weblogic version: 10.3.0
EJB version: 3.0

2 个答案:

答案 0 :(得分:7)

仅当您有多个类加载器时才会发生这种情况。我不会在EJB中使用静态初始化器,依赖于EJB生命周期钩子或将初始化器导出到非托管类中。

EJB 3.1添加了@Singleton和@Startup等注释,但不幸的是,在3.0中,您仍然坚持使用基于提供程序的解决方案来实现这些保证。

管理员与常规服务器行为相当普遍,因为WebLogic通常会部署到这两者。有关详细信息,请参阅this page

对于Weblogic关闭挂钩,请检查this documentation page

答案 1 :(得分:4)

是的,如果您实际上已经加载了两个不同的类副本,那么您可以多次执行静态初始化程序的唯一方法就是这样。只有当你有两个加载类的不同类加载器时才会发生这种情况。

防止这种情况的方法是安排有问题的类由两个类加载器的共同祖先类加载器加载。我不知道你将如何使用Weblogic,但是对于Tomcat,你会将相关的JAR文件放入指定的公共库目录中,该目录由容器中运行的所有webapp共享。