Possible JDK error in System.console ()

The following code is represented by the java.lang.System.console() method:

 private static volatile Console cons = null; /** * Returns the unique {@link java.io.Console Console} object associated * with the current Java virtual machine, if any. * * @return The system console, if any, otherwise <tt>null</tt>. * * @since 1.6 */ public static Console console() { if (cons == null) { synchronized (System.class) { cons = sun.misc.SharedSecrets.getJavaIOAccess().console(); } } return cons; } 

In my opinion, this is a mistake in this method. We must write this as follows:

 public static Console console() { if (cons == null) { synchronized (System.class) { if (cons == null) cons = sun.misc.SharedSecrets.getJavaIOAccess().console(); } } return cons; } 

I'm right? What do you think?

+5
source share
2 answers

If you look at the JavaIOAccess implementation , you will find that there is a null check inside it:

 public Console console() { if (istty()) { if (cons == null) cons = new Console(); return cons; } return null; } 

Since this method is the only way to initialize this variable, this is not a problem when the nested null check is in another method. Cannot get two different Console objects.

+3
source

This is not true. You can assign a value to it, and it has already been initialized. I think that zero checking is redundant, it is already being checked from the outside and as Tagir Valeev suggested inside the JavaIoAccess console implementation.

Perhaps you are thinking of a thread conflict, and since initialization takes place inside the synchronization block, several threads accessing it at the same time will trigger excessive reinitialization.

So you can say that this could be an improvement to reduce overhead rather than errors.

However, you should learn more about the Double Lock flag , it contains exactly your scenario. Details below


It is interesting to see the subtle problems of using it in J2SE 1.4 (and earlier versions) with various compilers.

After J2SE 5.0, this problem has been fixed.

The volatile keyword now ensures that multiple threads handle Singleton.

As you noticed, the static console object is unstable.

Using the implementation as described in the link above:

 private static volatile Console cons = null; public static Console console() { Console result = console; if (result == null) { synchronized (System.class) { result = console; if (result == null) { console = result =sun.misc.SharedSecrets.getJavaIOAccess().console(); } } } return result; } 

You can achieve this performance improvement:

Notice the result of the local variable, which seems unnecessary. This ensures that in cases where the console is already initialized (i.e. most of the time), the volatile field is available only once (due to the "return" result; "instead of" return console ; "), which can improve the overall method 25 percent performance - note: replace assistant with console for clarity

But I'm not sure how often console () is called from multiple threads for the first time - after that, initialization is no longer a problem due to checking for a null byte.

This solution also creates overhead, so the actual performance gain is controversial. Thus, your proposal (accepted above) can at best be considered an improvement.

+4
source

All Articles