2

I've heard that when instantiating a Java object there are actually 2 code commands happening, the memory allocation and the actual constructor.

So when declaring a singleton we need to write it like this:

if (instance == null) {
    synchronized (lock) {
        if (instance == null) {
            var tmp = new SingletonObject();
            instance = tmp;
        }
    }
}

I wanted to know if this applies to try catch finally as well. or is this problem occur only in threads?

FileOutputSteam out = null;
try {
    out = new FileOutputStream(path);
    ...
} finally {
    if (out != null) { // Does out can be non null but be corrupt?
        out.close();
    }
}
// BTW: This is an example, I know that there is try-with-resource

Thanks, Ido Sorozon

10
  • When it reaches finally block it must be a fully constructed out object Commented Aug 20, 2018 at 7:05
  • Your first example has nothing to do with any kind of constructor safety. It is just an example of the Double-checked locking for singletons. Commented Aug 20, 2018 at 7:06
  • @maba I am simply asking if this error is only a thread sync error or general error Commented Aug 20, 2018 at 7:09
  • 1
    Java guarantees that a non-null object reference has successfully executed its constructor without error. You can not have a "non null but corrupted" object, as long as the class does not require some extra steps to be initialized (thinking of InitializingBean of Spring or similar concepts) Commented Aug 20, 2018 at 7:25
  • 2
    @IdoSorozon yes I did. This has nothing to do with risky constructor. It only apply to multithreaded environment. Commented Aug 20, 2018 at 7:31

2 Answers 2

1

The null check in the finally block is there to avoid a NullPointerException because out may have failed initialization.

In other words, if the call to new FileOutputStream(path) ends in an exception, then out will not be set to an object. That means that the assignment out = new FileOutputStream(path) won't happen, and out will be null. And if it's null, out.close() in the finally block will encounter a NullPointerException.

Remember that finally will be run whether new FileOutputStream(path) raised an exception or not (that means, whether the assignment out = new FileOutputStream(path) failed or not), so the null check is there for the case where it failed.

And regarding // Does out can be non null but be corrupt?, then answer is No. In this finally block, out is either null (error occurred and assignment didn't happen) or a healthy FileOutputStream object resulting from a successful constructor call. There's no partial state.

Sign up to request clarification or add additional context in comments.

10 Comments

How does this answares my question? Try to explain my question to yourself and you will see that your answare is not relevant
I guess the OP is concerned with safe publication in the first case (var tmp = new SingletonObject(); instance = tmp;)
@user7 I took it that the question assumes out won't be assigned at all if new FileOutputStream(path) raises an exception...
@ernest_k This is exactly what I asked, whether out will be assigned even when new FileOutputStream(path) throws an Exception
@IdoSorozon Yeah. I subsequently edited the post. See the very last part of the answer.
|
0

The explanation of why that is necessary is wrong, but yes, if your singleton can be accessed by more than one thread, you need some locking mechanism in order to prevent two threads to initialize the singleton at the same time. You are using the double-checked locking pattern, which is one of the recommended ways to do that.

In your second example you are using local variables. They can only be accessed by the current thread, so no, you don't need to use synchronization there.

By the way, if you use Java 7 or higher, the try-with-resources construct is preferable:

try (FileOutputStream out = new FileOutputStream(path)) {
    ...
}

which (except for the scope of out) is equivalent to your second snippet.

2 Comments

I see that you didn't read my question to the end, I've wtitten that I am aware that try-with-resource exist
@IdoSorozon Yes, I see now that I skipped reading the code comment at the end.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.