Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, June 28, 2011

Advanced Java Multi-threading - Gotchas around thread-safety!

Went through the initial pages from the book Java Concurreny in Practice - Brian Goetz and found it awesome. Thought of sharing some key learnings...

1. A Java Class is said to be threadsafe, if it behaves the same way in both single and multi threaded environment.

2. A Java Class should always be designed by keeping "multi-threaded issues" in mind, as these days, the Java Class hardly work in Single threaded environment. When a class is being called by a framework, it is most likely invoked by a thread. A typical example is a TimerTask invoked by Timer.

3. Stateless objects are always thread safe. By stateless objects we mean those objects of classes which do not have any instance variables defined to hold the state of the object. The objects of these classes are always thread-safe, because there is no data to share between threads.

4. What are class invariants?
The states of objects that have some relationship to each other all the time. Say, for example, if there are two instance variables inside an object which are related like dateOfBirth and Age, then whenever dateOfBirth gets updated, the age should be updated atomically. The class invariants here are dateOfBirth and age and these must always be protected within a critical section.

5. What is reentrancy?
The intrinsic locks (the object locks) is acquired on a per-thread basis, as opposed to, a per-invocation basis in posix threads. The default locking behavior of pthreads (posix threads) mutexes are on per-invocation basis. The JVM associates a counter with the thread and whenever the thread which already acquired the lock tries to grab the same lock again, the JVM allows the thread to proceed further, after incrementing the associated counter. This is defined as reentrant.

6. Significance of volatile variables.
In multi-processor/multi-core CPU hardware, there are optimizations to temporarily store data in CPU cache or registers for a while, before updating the in-memory location. For a thread to always make sure that, it reads the most recent value of a shared data, mark it as volatile. So that, the underlying optimizations on locality of references are turned off.

7. Immutable objects are always thread safe. The objects whose state cannot be changed after construction are said to be immutable. When a state cannot be modified, it is always thread-safe.

Thursday, June 9, 2011

Issue with linux softlink which is part of a running JVM's classpath...

We observed a strange problem with Weblogic JVM in 10.3.2 version:

1) We're adding the following as classpath during the cluster/server startup. Please note that, "config" below is a symbolic link and this gets into the Weblogic JVM's classpath.

/mydrive/myfolder/myprojects/project/config

config -> project-1.1/config

2) The application is deployed and it works fine.

3) During the next release of the application, the "config" symbolic link used in the JVM classpath has been changed as below and the old project folder was removed. (THIS IS THE ISSUE).
config -> project-1.2/config

4) Now the newly deployed application is trying to come up to ACTIVE state. As part of initializing the app, it reads a properties file from the classpath (which is supposed to be referenced through the config soft link in the classpath).

5) At this stage, the Weblogic JVM is still holding the softlink reference to the previous deployment folder which NO MORE EXISTS. I verified this with a sample program and have described about it further below.

6) As a result, the application throws FileNotFoundException.

More experiments:
I tried a simple experiment to reproduce this issue with a standalone JVM...

1) Create a folder: /mydrive/myfolder/myprojects/project.
2) Create two subfolders: project1 and project2.
3) Each folder must have config directory within itself and config folder should contain test.props with their own contents.
4) Create a config softlink at the base folder (/mydrive/myfolder/myprojects/project) to either project1/config or project2/config.
5) Create a Java file which will try to read the property file from the classpath ("test.props") and wait for a user input. And after user input is read, it should again read the same properties file.
6) After successfully compiling the program, run the program like: java -cp "/mydrive/myfolder/myprojects/project/config:." JavaFile
7) You will see the program reads the correct property file as pointed out through the softlink and waits for user input.
8) Now, on another terminal switch the config softlink to point to the other project's config folder, while the JVM is running on another terminal waiting for user input.
9) If you give 'Enter' on the waiting java process, it will READ again the test.props file AFRESH. But this time you can SEE IT STILL READS THE SAME OLD PROPERTY FILE AND NOT THE NEW ONE POINTED BY SOFTLINK.
10) If you had deleted the old projectX folder, instead of just changing the softlink as above, you will get null for the resource - test.props, which encounters just the same scenario as we observed in our application on Weblogic.


Bottom Line:
Never change a softlink that is part of a running JVM's classpath. This includes not just the soft link (versioned or non-versioned), but also the softlink contents. Instead add the PARENT FOLDER of the softlink in the JVM classpath, so that any changes to the softlink or contents of the softlink are decoupled from the running JVM.