Archive for the ‘Java’ Category

Multi-threading: Pitfalls when initializing static variables

Tuesday, December 9th, 2014

As a developer you often have to initialize static variables in a multi-threaded environment. The basic solution that most programmers apply is:

1
2
3
4
5
6
7
8
9
private static Object staticVar = null;
 
public static synchronized Object getStaticVar() {
    if (staticVar == null) {
        // initialize
        staticVar = ...
    }
    return staticVar;
}

This is a simple but expensive method. Each thread that needs the variable must synchronize with each other although the variable has long been initialized. So, usually the next step is to synchronize less:

1
2
3
4
5
6
7
8
9
10
11
12
private static Object SYNCHRONIZER = new Object();
private static Object staticVar = null;
 
public static Object getStaticVar() {
    if (staticVar == null) {
        synchronized (SYNCHRONIZER) {
            // initialize
            staticVar = ...
        }
    }
    return staticVar;
}

Yep. That does it, doesn’t it? The answer is: half! Imagine two simultaneous threads entering the method at the same time. If both will see staticVar being null then both will try to enter the synchronized block. And of course, both will initialize the variable nevertheless another thread did it before. So, we add another evaluation to ensure that only one thread will initialize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static Object SYNCHRONIZER = new Object();
private static Object staticVar = null;
 
public static Object getStaticVar() {
    if (staticVar == null) {
        synchronized (SYNCHRONIZER) {
            if (staticVar == null) {
               // initialize
               staticVar = ...
            }
        }
    }
    return staticVar;
}

Most books end here but omit a very crucial part. The code works perfect as long as the initialization is a simple operation only. Let’s make the initialization a bit more sophisticated:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static Object SYNCHRONIZER = new Object();
private static List<String> staticVar = null;
 
public static List<String> getStaticVar() {
    if (staticVar == null) {
        synchronized (SYNCHRONIZER) {
            if (staticVar == null) {
               // initialize
               staticVar = new ArrayList<String>();
               staticVar.add("value 1");
               staticVar.add("value 2");
               staticVar.add("value 3");
            }
        }
    }
    return staticVar;
}

The first glance doesn’t reveal anything. But it happened several times in one of my own applications that two threads were not correctly synchronized. Occasionally, one thread found the list to be empty. What happened?

The magic is that staticVar is being set at the very first beginning of the synchronized block. Meanwhile another thread was entering the method and saw the variable not being null. It immediately started using the list although it was not yet initialized completely. The correct solution is therefore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static Object SYNCHRONIZER = new Object();
private static List<String> staticVar = null;
 
public static List<String> getStaticVar() {
    if (staticVar == null) {
        synchronized (SYNCHRONIZER) {
            if (staticVar == null) {
               // initialize
               List<String> tmp = new ArrayList<String>();
               tmp.add("value 1");
               tmp.add("value 2");
               tmp.add("value 3");
               staticVar = tmp;
            }
        }
    }
    return staticVar;
}

For readability, we could refactor the method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static Object SYNCHRONIZER = new Object();
private static List<String> staticVar = null;
 
public static List<String> getStaticVar() {
    if (staticVar == null) {
        synchronized (SYNCHRONIZER) {
            if (staticVar == null) {
               staticVar = createList();
            }
        }
    }
    return staticVar;
}
 
private static List<String> createList() {
   // initialize
   List<String> tmp = new ArrayList<String>();
   tmp.add("value 1");
   tmp.add("value 2");
   tmp.add("value 3");
   return tmp;
}

RsBudget 2.0 released

Monday, August 11th, 2014

logoIt’s done. My first official Eclipse/RCP application is out. RsBudget is an Expense Tracker for everyone. I’ve been developing it now for three years while constantly using it for private purposes. That’s how it grew to its functionality as it is today. I simply used these previous versions in order to feel and learn what’s been missing. Now it’s up to you to tell me what there is to be done next (a few tasks are already waiting ;)).

The application still misses some features, e.g. nice graphical statistics. But I don’t regard them as a must-have so far. They will be added with next versions, some will be available as commercial add-ons later.

The main features are:

  • General Expense Planning
  • Monthly Expense Planning, Tracking and Control
  • Categorization of expenses
  • Comparison of planned and actual values
  • Free text field for personal notes for each month
  • Forecasting of balances and profit/loss
  • Statistics and History
  • Export of transaction records to Excel and CSV
  • Multi-language support (English and German)
  • Online Help
  • Online Update

RsBudget runs on all major desktop platforms (Windows, MacOS, Linux) with Java 7 installed. Just download your version here!

Eclipse RCP Common Feature launched

Monday, August 11th, 2014

Good news for all Eclipse developers that want to use some of my projects in their own Eclipse/RCP projects. I bundled some modules and projects into a Luna Eclipse Feature Plug-In – called RCP Common Feature.

You will need the Update Site http://download.ralph-schuster.eu/rcp-updates/luna/releases/ to be added in your IDE and install the feature as you would do with every other Eclipse feature plug-in.

These are the modules and projects currently bundled:

Furthermore, there are three more plug-ins available specific to Eclipse/E4 UI and logging. The feature plug-in is released under LGPL V3 license (as all projects bundled in it).

 

Luna Update: TranslationService not in context

Saturday, July 26th, 2014

After migrating my Eclipse/E4 application to the latest release Luna, I noticed that the TranslationService is not present anymore within the E4Workbench.getServiceContext(). At least not at the PostContextCreate stage of the application. This is not a big deal, as you can easily create this yourself:

1
2
3
4
5
6
7
8
9
10
11
12
   private static TranslationService TRANSLATIONS = getTopContext().get(TranslationService.class);
 
   public static TranslationService getTranslationService() {
      if (TRANSLATIONS == null) {
         TRANSLATIONS = getTopContext().get(TranslationService.class);
         if (TRANSLATIONS == null) {
            TRANSLATIONS = ContextInjectionFactory.make(BundleTranslationProvider.class, getTopContext());
            getTopContext().set(TranslationService.class, TRANSLATIONS);
         }
      }
      return TRANSLATIONS;
   }

Solution to “Tomcat can’t stop [Abandoned connection cleanup thread]”

Wednesday, July 9th, 2014

I am preparing a web service for one of my larger projects, using Tomcat, Hibernate and MySQL. While developing I stumbled across several Tomcat error messages that suggest some threads could not be stopped. Most of the threads could simply be vanished by calling Hibernate’s SessionFactory.close() method. However, a few threads seem to remain, e.g.

Jul 09, 2014 10:55:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/examples] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to 
unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jul 09, 2014 10:55:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/examples] appears to have started a thread named [Abandoned connection cleanup 
thread] but has failed to stop it. This is very likely to create a memory leak.

and in fact, Tomcat stopped working after a few redeployments due to memory problems. Two main reasons:

  1. The MySQL AbandonedConnectionCleanupThread does not shutdown correctly.
  2. The MySQL J/Connector driver doesn’t unregister anymore from the DriverManager.

At least with J/Connector V5.1.31 the problem disappears by using this shutdown procedure (hooked in by a ServletContextListener):

1
2
3
4
5
6
7
8
9
10
11
12
13
   try {
      com.mysql.jdbc.AbandonedConnectionCleanupThread.shutdown();
   } catch (Throwable t) {}
   // This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks
   Enumeration<java .sql.Driver> drivers = java.sql.DriverManager.getDrivers();
   while (drivers.hasMoreElements()) {
      java.sql.Driver driver = drivers.nextElement();
      try {
         java.sql.DriverManager.deregisterDriver(driver);
      } catch (Throwable t) {}
   }
   try { Thread.sleep(2000L); } catch (Exception e) {}
</java>

I still have to observe long-term effects and will keep you informed.

Using Pooled Data Connections with RS Libs Data Hibernate Library

Thursday, July 3rd, 2014

The standard way of configuring a data source for RSLib’s Data Hibernate Library is to use the driver’s DataSource implementation as shown here:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<dbconfig>
   <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
 
   <datasource class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource">
      <property name="url">jdbc:mysql://db-host:3306/db-name</property>
      <property name="user">db-user</property>
      <property name="password">db-password</property>
   </datasource>
</dbconfig>

However, this setup will result in creating a new connection each time you start a new transaction. This is most likely not what you want in a productive application. Instead you shall use a pooled DataSource, as the c3p0 project provides:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<dbconfig>
   <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
 
   <datasource class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="driverClass">com.mysql.jdbc.Driver</property>
      <property name="jdbcUrl">jdbc:mysql://db-host:3306/db-name?autoReconnect=true</property>
      <property name="user">db-user</property>
      <property name="password">db-password</property>
   </datasource>
</dbconfig>

I stumbled across this problem while implementing a project and receiving a

java.net.SocketException: No buffer space available (maximum connections reached?): connect

exception.

Update July 26nd: You will need the autoReconnect=true parameter with MySQL to avoid problems with connections in the pools not being used for quite a long time.

Update August 18th: This URL parameter doesn’t work correctly. The solution is to add a c3p0.properties file in your classpath:

1
2
3
4
5
6
7
8
9
10
11
c3p0.maxPoolSize=50
c3p0.minPoolSize=5
c3p0.timeout=0
c3p0.maxStatements=0
c3p0.maxStatementsPerConnection=0
c3p0.idleConnectionTestPeriod=300
c3p0.acquireIncrement=1
c3p0.validate=true
c3p0.preferredTestQuery=SELECT 1;
c3p0.testConnectionOnCheckin=false
c3p0.testConnectionOnCheckout=true

(Don’t try to set these properties via your hibernate.cfg file. Some of them cannot be set there!)

B4J V2.0.1 releaseed

Wednesday, May 14th, 2014

A new version 2.0.1 of B4J has been released. It fixes issues found by static code analysis. A complete change log is available as well as the mandatory Maven Site.

You can download the new version here or visit the Homepage of the utility where you will find more documentation.

The Maven coordinates are:

<dependency>
      <groupId>eu.ralph-schuster</groupId>
      <artifactId>b4j</artifactId>
      <version>2.0.1</version>
</dependency>

CSV/Excel Utility Package V2.7.1 released

Thursday, May 8th, 2014

The new version 2.7.1 fixes issues found by static code analysis. A complete change log is available as well as the mandatory Maven Site.

You can download the new version here or visit the Homepage of the utility where you will find some examples on how to use it.

The Maven coordinates are:

<dependency>
      <groupId>eu.ralph-schuster</groupId>
      <artifactId>csv</artifactId>
      <version>2.7.1</version>
</dependency>

RS Library V1.2.5 released

Thursday, May 8th, 2014

I released RS Library V1.2.5 which mainly contains fixes to issues found by static code analysis. A complete list of changes can be found here.

The Maven repositories shall be up-to-date by now. The Maven coordinates are:

   <dependency>
      <groupId>eu.ralph-schuster</groupId>
      <artifactId>baselib</artifactId>
      <version>1.2.5</version>
   </dependency>
 
   <dependency>
      <groupId>eu.ralph-schuster</groupId>
      <artifactId>data</artifactId>
      <version>1.2.5</version>
   </dependency>
 
   <dependency>
      <groupId>eu.ralph-schuster</groupId>
      <artifactId>data-file</artifactId>
      <version>1.2.5</version>
   </dependency>
 
   <dependency>
      <groupId>eu.ralph-schuster</groupId>
      <artifactId>data-hibernate</artifactId>
      <version>1.2.5</version>
   </dependency>
 
   <dependency>
      <groupId>eu.ralph-schuster</groupId>
      <artifactId>templating</artifactId>
      <version>1.2.5</version>
   </dependency>

Multiple Releases

Monday, March 10th, 2014

The last few days I released new versions of three of my projects.

All projects are available through Maven Central.