Singleton is not really singleton

I have a situation where I am sharing a singleton between my code that launches the embedded server and my web application. I have a war with classes and a deployment tool. When I print instances, I see:

abc.Abc@173a10f abc.Abc@105738 

So it is not solitary. How it works?


My Jetty server-side startup code:

 public static void main(String[] args) throws Exception { System.out.println(MySingleton.getInstance()); // start Jetty here and deploy war with WebAppContext() } 

My ServletContextListener side code:

 public class AppServletContextListener implements ServletContextListener{ @Override public void contextInitialized(ServletContextEvent arg0) { System.out.println(MySingleton.getInstance()); } } 

My singleton:

 public class MySingleton { private static MySingleton INSTANCE = new MySingleton(); private MySingleton () {} public static MySingleton getInstance() { return INSTANCE; } } 

I forced an exception inside the constructor. Looks like I'm getting two different.

 java.lang.Exception at api.MySingleton.<init>(MySingleton.java:33) at api.MySingleton.<clinit>(MySingleton.java:22) at my.project.StartJetty.main(StartJetty.java:41) java.lang.Exception at api.MySingleton.<init>(MySingleton.java:33) at api.MySingleton.<clinit>(MySingleton.java:22) at api.AppServletContextListener.contextInitialized(AppServletContextListener.java:25) at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:640) at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:229) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1208) at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:586) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:449) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:58) at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:58) at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89) at org.eclipse.jetty.server.Server.doStart(Server.java:258) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:58) at my.project.StartJetty.main(StartJetty.java:66) 
+4
source share
3 answers

Take a look at the Jetty documentation. You can play with class loading configurations.

When set to true, Jetty uses the usual JavaSE class load priority and gives priority to the parent / system class loader. This avoids the release of multiple versions of the class in webapp, but the version provided by the parent / system loader should be the correct version for all web configurations that you configure in this way.

This is exactly what you are describing. One instance of MySingleton loaded by the main Java program, and the other is loaded by the Jetty class loader.

+5
source

Printing the stack trace in the constructor should provide you with the information you need to find out where it is created and what order. The Singleton template is a dangerous thing, it is usually better to do it differently.

+2
source

Your ServletContextListener and core classes are loaded by different class loaders. Whenever a class is loaded, its static block will be executed. so you get two instances ...

If you want to make sure that the same classloader loads your singleton, you must specify the classloader yourself.

check this link for more details http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page=2

+2
source

Source: https://habr.com/ru/post/1501727/


All Articles