2007/10/25

Singleton vs. Multiton & Synchronization

1. The classic java singleton synchronization problem

public class Singleton{
private static Singleton instance;

/** Prevents instantiating by other classes. */
private Singleton(){}

public static synchronized Singleton getInstance()
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
The synchronized keyword on the getInstance() method is the evil. In a multi-thread environment, every thread will be blocked by each other when trying to grab the singleton instance. This is the classic java singleton synchronization problem.

2. The traditional solution using a static variable

public class Singleton {
private final static Singleton instance = new Singleton();

/** Prevents instantiating by other classes. */
private Singleton() {}

public static Singleton getInstance() {
return instance;
}
}
The singleton instance is initialized during the class loading time. No synchronization is necessary on the getInstance level

3. The Classic synchronized Multiton

public class Multiton{
private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();

private Multiton(){}

public static Multiton getInstance(Object key){
synchronized (instances) {
// Our "per key" singleton
Multiton instance;
if ((instance = instances.get(key)) == null) {
// Lazily create instance and add it to the map
instance = new Multiton();
instances.put(key, instance);
}
return instance;
}
}
}
The Multiton pattern begins with the concept of the Singleton pattern and expands it into an object pool of keys to objects. Instead of having a single instance per runtime, the Multiton pattern ensures a single instance per key. It simplifies retrieval of shared objects in an application.

As we noticed from the above scriptlet, the access to the getInstance() method is synchronized to ensure the uniqueness of instance per key. This, again, is a performance bottleneck in multi-thread environment. The traditional 'static' solution for Singleton pattern can't be used here since the keys are passed into the Multiton on-the-fly. We have no way to predict how many keys will be passed into the Multiton during the runtime.

4. The double-checked locking solution

public class Multiton {
private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();

public static Multiton getInstance(Object key) {
// Our "per key" singleton
Multiton instance;
if ((instance = instances.get(key)) == null){
synchronized(instances){
if ((instance = instances.get(key)) == null){
instance = new Multiton();
instances.put(key, instance);
}
}
}
return instance;
}
}
Yes the double-checked locking does not work for Singleton (http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html), but it does work for our Multiton pattern. Reason? We have our intermediate HashMap object sits in between. Actually we can use the HashMap to solve the Singleton double-checked locking problem as well, if we don't already have the more elegant solution using a static variable.

5. An alternative solution: Using the Java 5 ConcurrentMap

public class Multiton {
private static final ConcurrentMap<Object, Multiton> instances = new ConcurrentHashMap<Object, Multiton>();

public static Multiton getInstance(Object key) {
// Our "per key" singleton
if (instances.get(key) == null){
// Lazily create instance and try to add it to the map
Multiton instance = new Multiton();
instances.putIfAbsent(key, instance);
}
return instances.get(key);
}
}
The Java 5 ConcurrentMap.putIfAbsent(), being an atomic operation, returns the previous value associated with the key instead of the new suggested value. This ensures the uniqueness of the Multiton instance inside the ConcurrentMap.

In this solution, before a key object has been associated with a Multiton object, if two or more threads are trying to retrieve the instance with the same key object, it's possible that multiple Multiton instance will be created inside the if() block. However, the ConcurrentMap ensures that a same Multiton instance is to be returned to the caller. Extra instances are eligible for Garbage Collection as soon as the method returns. You may not want to use this solution if the creation of the Multiton instance is an expensive operation, as in certain situation.

6. Afterwords

Synchronization and double-checked locking is such an interesting classic java topic, I'm so much wanting to participating in any sort of discussion, it'll always be interesting :)

2007/10/24

Java Performance - ALL Tips

Oh yes, this is a complete list of ALL Java perfomance tips. Thanks for www.javaperformancetuning.com

http://www.javaperformancetuning.com/tips/rawtips.shtml

2007/10/23

Bean Definitions Tip1: Avoid Circular References

Spring is a really powerful framework, which is not only providing the JEE similar or much better and lighter container services, but also providing a straightforward declarative and configuration driven bean definition model. With the flexibility and capability of bean definition mechanism, especially when you unleashing the power of XML schema based context file introduced since Spring 2.0, you can almost do any sorts of bean wiring, parameter configuration, application assembling tasks. After you use it, I bet you will forget all the unpleasant and cumbersome JEE configuration files and the coarse grained Enterprise Beans. However, when dealing with bean definitions, it's still very tricky and the similar problems probably happen as in your traditional programmatic approach.

One typical problem is that the bean definition circular referencing. This is the circumstance under which there are beans relying on each others instance before they could be instantiated by Spring container.

For below example:

public class BeanA {
BeanB b;
public BeanA(BeanB beanB){
b = beanB;
}
public void print(String s) {
System.out.print(s);
}
public void foo(){
b.foo();
}
}

public class BeanB {
private BeanA a;
public BeanB(BeanA beanA){
a = beanA;
}

public void print(String s){
a.print(s);
}

public void foo() {
System.out.print("foo!");
}
}

public class TestStub {
public static void main(String[] args){
AbstractApplicationContext ctxt= new ClassPathXmlApplicationContext("beandef.xml");
}
}

...bean definitions in beandef.xml ...

<bean id="beanA" class="BeanA">
<constructor-arg ref="beanB" />
</bean>
<bean id="beanB" class="BeanB">
<constructor-arg ref="beanA"/>
</bean>

When you run TestStub, it will show following exception (pay attention to the underline):

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanA' defined in class path resource [beandef.xml]: Cannot resolve reference to bean 'beanB' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanB' defined in class path resource [beandef.xml]: Cannot resolve reference to bean 'beanA' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanB' defined in class path resource [beandef.xml]: Cannot resolve reference to bean 'beanA' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?

It's a simple sample of bean circular reference. Specifically, the container tried to instantiate "beanA" first, then it found "beanA" need a reference of "beanB" as constructor argument; subsequently, it tried to create an instance of "BeanB" as "beanB", but this time the "beanB" need a "beanA" instance as a constructor reference argument that is still creation pending waiting for "beanB". This situation confused the container and it can not resolve all the bean references. Then it came the complains of exception. This circular reference problem was caused by circular references of bean by means of Constructor Injection.

To solve this issue, one option is that replace constructor reference to "beanA" of "beanB" with a setter injection. Then the container will not try to create the "beanB" with the "beanB" reference at same time. Instead, it will defer this by injecting the "beanA" reference latter on via "setter" method of "BeanB" after the "beanA" has been created. The same changes happen to "BeanA". It needs some tweaks to the code and bean definitions as well.

public class BeanA {
BeanB b;
public BeanA(){
}
public void setBeanB(BeanB b){
this.b = b;
}
public void print(String s) {
System.out.print(s);
}
public void foo(){
b.foo();
}
}


public class BeanB {
private BeanA a;
public BeanB(){
}

public void setBeanA(BeanA a){
this.a = a;
}
public void print(String s){
a.print(s);
}

public void foo() {
System.out.print("foo!");
}
}


...

<bean id="beanA" class="BeanA">
<property name="beanB" ref="beanB"/>
</bean>
<bean id="beanB" class="BeanB">
<property name="beanA" ref="beanA"/>
</bean>

...

This time, the Sping was very happy to create all the beans.

An alternative option is still workable for this case but a lit bit tricky related with bean instantiating order. We can ask "beanA" injected "beanB" by setter, whereas "beanB" can still use the constructor injection. But wait, the order of bean definition is very important. You can not let constructor injected "beanB" defined before setter injected "beanA".

public class BeanA {
BeanB b;
public BeanA(){
}
public void setBeanB(BeanB b){
this.b = b;
}
public void print(String s) {
System.out.print(s);
}
public void foo(){
b.foo();
}
}

public class BeanB {
private BeanA a;
public BeanB(BeanA a){
this.a = a;
}

public void print(String s){
a.print(s);
}

public void foo() {
System.out.print("foo!");
}
}

...

<bean id="beanA" class="BeanA">
<property name="beanB" ref="beanB"/>
</bean>
<bean id="beanB" class="BeanB">
<constructor-arg ref="beanA"/>
</bean>

...

This works very well. If you move the "beanB" definition before "beanA", it will not work because the "beanA" will need a creating "beanB".

In a nutshell, the circular reference problem is very typical for a sophisticated "Spring" application if you did not cook it very well. It will cost you time to debug and fix it. But not just that. Because the nature of configuration driven of "Spring", the same bean definition file itself could have huge chances to be manipulated by different personnel, thus, more chances of introducing new errors regarding the "Spring" competency level. I will talk about in future sessions how to address this issue by establishing your project or organization level bean definition schema extended from "Spring" base schema. In this way, it mandates some of important project wise constraints for bean definition, such as available tags, bean types, data types etc. Thus, it could reduce some errors caused by arbitrary string parameters or typos in bean definition files for your project.

It's strongly recommended to use setter injection for bean wiring and bean reference injection. If it's very necessary to do constructor based reference injection, and unfortunately involved with circular reference, please well comment or document the bean definition and put notices for future maintaining people. You don't just want someone else happened to ruin your whole fragile bean constructor injection hierarchy someday, do you?

2007/10/17

IntelliJ IDEA Performance

There're some concerns about IntelliJ IDEA Performance. And here is the tips that I used to make mine run fast. Some of them come from my own experience, some of them come from the know-everything internet.

  • Make sure you have all your libraries on your local harddrive (as opposed to mounted network drive). After I moved all my libraries from a network drive to local harddrive, the time for a 'make' on the project is reduced from around 60 seconds to just 5-7 seconds!
  • Defragment your Disk and reboot your computer. IDEA creates lots of small files and too much fragmentation is a nightmare.
  • Turn off Anti Virus completely. Yes I mean completely. It affects the performance dramatically.
  • Turning off Local History or even reducing the number of history days improved the performance significantly.
  • Adjust VM settings. Here is my idea.exe.vmoptions file (on windows):
-Xms512m
-Xmx512m
-XX:MaxPermSize=99m
-ea

Change it as you see fit per your hardware configuration.

More information is available at http://blogs.jetbrains.com/idea/2006/04/configuring-intellij-idea-vm-options/.
  • The Debugger in IDEA may work slowly if the Force classic VM option is not selected in the File Project Properties Debugger dialog. Using Method Breakpoints may also slow down the debugging process. I had two breakpoints on the method name instead of the first line of the method. It was taking a half hour to get to the breakpoint Changing these to line breakpoints gave me two orders of magniture
  • You may notice IDEA hang for several seconds when you switch to it from other applicationDisable Settings General Synchronize files on frame activation.
  • Disable windows paging file if you have enough memory. Get more memory if you don't have enough. Swapping is a performance nightmare.
  • Turn off windows indexing services, either set it to Disabled or Manual unless you do lots of file system search (even you do, I recommend Google Desktop Search). IDEA use lots of small files so background indexing can have a big negative effect on it's performance.
  • Control Panel/System/Properties/Advanced/Visual Effcts, Adjust for best performance. Unless you're willing to sacrify performance for visual effects like windows animation, fading/sliding etc.

2007/10/12

Hibernate Mapping Cheat Sheet

Here's a nice hibernate mapping cheat sheet. Good reference when programming.

http://ndpsoftware.com/HibernateMappingCheatSheet.html

SpringContextAware JUnit TestCase

In order to run Junit test case outside of a J2EE container, the test case need to initialize the Spring framework properly. I created this abstract class SpringContextAware, which extends from junit.framework.TestCase and initialize the Spring framework in it's setUp() method. User Test Cases that extends from this class will be running with Spring context loaded already.

public abstract class SpringContextAware extends TestCase {
public SpringContextAware(String name){
super(name);
}

public void setUp() throws Exception{
if (SpringApplicationContext.getApplicationContext()==null) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{
// list your context files here
"context-service.xml",
"context-hibernate.xml"
});
ctx.registerShutdownHook();
}
}

public void tearDown() throws Exception{
}
}


Here is the SpringApplicationContext class, basically it allows java classes not defined as a spring bean to be able to access the Spring Application Context.

public class SpringApplicationContext implements ApplicationContextAware {

private static ApplicationContext context;

public static ApplicationContext getApplicationContext() {
return SpringApplicationContext.context;
}

/**
* This method is called from within the ApplicationContext once it is
* done starting up, it will stick a reference to itself into this bean.
*
* @param context a reference to the ApplicationContext.
*/
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringApplicationContext.context = context;
}

/**
*This is about the same as context.getBean("beanName"), except it has its
* own static handle to the Spring context, so calling this method statically
* will give access to the beans by name in the Spring application context.
* As in the context.getBean("beanName") call, the caller must cast to the
* appropriate target class. If the bean does not exist, then a Runtime error
* will be thrown.
*
* @param beanName the name of the bean to get.
* @return an Object reference to the named bean.
*/
public static Object getBean(String beanName) {
return context.getBean(beanName);
}
}


This bean itself however, needs to be defined in the Spring Context XML file:

<!-- provide access to spring application context -->
<bean id="springApplicationContext" class="com.blah.blah.SpringApplicationContext">
</bean>


Any comments are welcome :)

EHCache Singleton CacheManager

Here's the problem, when we enable the hibernate secondary cache using org.hibernate.cache.EHCacheProvider, and enable ACEGI user cache using

<property name="userCache">
<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache">
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheName" value="AcegiUserCache">
</property>
</bean>
</property>
</bean>
</property>

They belongs to two different cache manager.

Instead of have to configure 2 different cache manager separately, have to have separate cache invalidating thread etc, we can fall back to the EHCache Singleton CacheManager.

hibernate.cache.provider_class=net.sf.ehcache.hibernate.SingletonEhCacheProvider

Now ACEGI will use the same EHCache CacheManager. They can be configured in the same ehcache.xml file. Yup!

Well well... why another J2EE blog? I benefited from other people's technical blogs, and guess what, it's a good idea to contribute some of my works too. Hope it's helpful and useful, to all of your folks.