Posts

Showing posts from June, 2018

Looking into Java's Future: Empty Value Types

Although the promising Java value types are not imminent, I still enjoy nosing around occasionally in the OpenJDK valhalla-dev mailing list to see how things appear to be progressing and to get an idea of what is to come. Admittedly, there are some discussions that are beyond my understanding given my limited exposure to the terms used and the low-level specifics of some of these messages. However, there are occasionally messages and threads that I understand well what is being written and find interesting. A recent example of this is the " Empty value type ? " thread. Rémi Forax starts the thread by asking "Is empty value type targeted for LW1 ?" The example error message included with that question shows a LinkageError and ClassFormatError with the message "Value Types do not support zero instance size yet". The response to this question from Tobias Hartmann answers, "No, empty value types are not planned to be supported for LW1 ." Befor...

Deferred Execution with Java's Consumer

In an earlier blog post (" Deferred Execution with Java's Supplier ") I referenced Cay Horstmann 's statement in the book " Java SE8 for the Really Impatient " regarding lambda expressions, "The point of all lambdas is deferred execution ." Horstmann wrote an article called " Lambda Expressions in Java 8 " for Dr. Dobb's magazine in its final year in which he wrote a similar statement using different terminology, "A lambda expression is a block of code that you can pass around so it can be executed later, just once or multiple times." In that earlier post , I looked at how the standard functional interface Supplier is used with lambda expressions in the JDK to support deferred execution for cases where a single value is "supplied only when necessary" and without any argument passed to it. In this post, I focus on JDK-provided examples of using the Consumer standard functional interface to "consume" ...

Java's Ternary is Tricky with Autoboxing/Unboxing

The comments section of the DZone-syndicated version of my post " JDK 8 Versus JDK 10: Ternary/Unboxing Difference " had an interesting discussion regarding the "why" of the "fix" for how Java handles autoboxing/unboxing in conjunction with use of the ternary operator (AKA " conditional operator "). This post expands on that discussion with a few more details. One of the points made in the discussion is that the logic for how primitives and reference types are handled in a ternary operator when autoboxing or unboxing is required can be less than intuitive. For compelling evidence of this, one only needs to look at the number of bugs written for perceived problems with Java's conditional operator's behavior when autoboxing and unboxing are involved: JDK-6211553 : Unboxing in conditional operator might cause null pointer exception The "EVALUATION" section states, "This is not a bug." It then explains that the obs...

JDK 11: Beginning of the End for Java Serialization?

In the blog post " Using Google's Protocol Buffers with Java ," I quoted Josh Bloch's Third Edition of Effective Java , in which he wrote, "There is no reason to use Java serialization in any new system you write." Bloch recommends using "cross-platform structured-data representations" instead of Java's deserialization. The proposed JDK 11 API documentation will include a much stronger statement about use of Java deserialization and this is briefly covered in this post. The second draft of the " Java SE 11 (18.9) ( JSR 384 )" specification includes an "A2 Annex" called " API Specification differences " that includes the changes coming to the Javadoc-based documentation for package java.io . The new java.io package documentation will include this high-level warning comment: Warning: Deserialization of untrusted data is inherently dangerous and should be avoided. Untrusted data should be carefully validated acc...

JDK 8 BigInteger Exact Narrowing Conversion Methods

In the blog post " Exact Conversion of Long to Int in Java ," I discussed using Math.toIntExact(Long) to exactly convert a Long to an int or else throw an ArithmeticException if this narrowing conversion is not possible. That method was introduced with JDK 8 , which also introduced similar narrowing conversion methods to the BigInteger class. Those BigInteger methods are the topic of this post. BigInteger had four new "exact" methods added to it in JDK 8: byteValueExact() - Converts BigInteger value exactly to byte if possible shortValueExact() - Converts BigInteger value to short if possible intValueExact() - Converts BigInteger value exactly to int if possible longValueExact() - Converts BigInteger value exactly to long if possible As described above, each of these four "exact" methods added to BigInteger with JDK 8 allow for the BigInteger 's value to be narrowed to the data type in the method name, if that is possible. Because...

JDK 8 Versus JDK 10: Ternary/Unboxing Difference

A recent Nicolai Parlog ( @nipafx ) tweet caught my attention because it referenced an interesting StackOverflow discussion on a changed behavior between JDK 8 and JDK 10 and asked "Why?" The issue cited on the StackOverflow thread by SerCe ultimately came down to the implementation being changed between JDK 8 and JDK 10 to correctly implement the Java Language Specification. The following code listing is (very slightly) adapted from the original example provided by SerCe on the StackOverflow thread. Adapted Example That Behaves Differently in JDK 10 Versus JDK 8 public static void demoSerCeExample() { try { final Double doubleValue = false ? 1.0 : new HashMap<String, Double>().get("1"); out.println("Double Value: " + doubleValue); } catch (Exception exception) { out.println("ERROR in 'demoSerCeExample': " + exception); } } When the above code is compiled and executed with JDK 8, it g...

Exact Conversion of Long to Int in Java

With all the shiny things ( lambda expressions , streams , Optional , the new Date/Time API , etc.) to distract my attention that came with JDK 8 , I did not pay much attention to the addition of the method Math.toIntExact() . However, this small addition can be pretty useful in its own right. The Javadoc documentation for Math.toIntExact​(long) states, "Returns the value of the long argument; throwing an exception if the value overflows an int ." This is particularly useful in situations where one is given or already has a Long and needs to call an API that expects an int . It's best, of course, if the APIs could be changed to use the same datatype, but sometimes this is out of one's control. When one needs to force a Long into an int there is potential for integer overflow because the numeric value of the Long may have a greater magnitude than the int can accurately represent. If one is told that a given Long will never be larger than what an int can ho...

Peeking Inside Java Streams with Stream.peek

For a Java developer new to JDK 8-introduced pipelines and streams , the peek(Consumer) method provided by the Stream interface can be a useful tool to help visualize how streams operations behave. Even Java developers who are more familiar with Java streams and aggregation operations may occasionally find Stream.peek(Consumer) useful for understanding the implications and interactions of complex intermediate stream operations. The Stream.peek(Consumer) method expects a Consumer , which is essentially a block of code that accepts a single argument and returns nothing. The peek(Consumer) method returns the same elements of the stream that were passed to it, so there will be no changes to the contents of the stream unless the block of code passed to the peek(Consumer) method mutates the objects in the stream. It's likely that the vast majority of the uses of Stream.peek(Consumer) are read-only printing of the contents of the objects in the stream at the time of invocation of ...

[JDK 11] Class Loader Hierarchy Details Coming to jcmd

I've been a fan of the diagnostic command-line tool jcmd since hearing about jcmd at JavaOne 2012 . I've used this tool extensively since then and have blogged multiple times about this tool: jcmd: One JDK Command-Line Tool to Rule Them All Determining the Active HotSpot Garbage Collector Programmatic jcmd Access JavaOne 2012: Diagnosing Your Application on the JVM After numerous years of developing with Java, it's my opinion that the classloader is the source of some of the most difficult defects encountered during development and debugging. Given this observation and given my interest in jcmd , I am very interested in JDK-8203682 ["Add jcmd 'VM.classloaders' command to print out class loader hierarchy, details"]. The "Description" for JDK-8203682 states, "It would be helpful, as a complement to VM.classloader_stats , to have a command to print out the class loader hierarchy and class loader details." In other words, this command ...

Thread Methods destroy() and stop(Throwable) Removed in JDK 11

The message " RFR(s): 8204243: remove Thread.destroy() and Thread.stop(Throwable) " by @DrDeprecator (Stuart Marks) on the core-libs-dev OpenJDK mailing list is a request for review (RFR) of a change set associated with JDK-8204243 ["remove Thread.destroy() and Thread.stop(Throwable)"]. Both the bug report and the mailing list message describe the history of these two referenced Thread methods and explain that neither method really does anything useful. The JDK 10 Javadoc API documentation for java.lang.Thread shows six methods on the Thread class that are deprecated, three of which are explicitly marked for removal. The table below summarizes these deprecated Thread methods. Methods Deprecated in java.lang.Thread as of JDK 10 Method Deprecated Since For Removal? JDK 10 Status countStackFrames() 1.2 Yes Depends on deprecated suspend() destroy() 1.5 Yes Throws NoSuchMethodError since inception ( never implemented ) resume() 1.2 No ...

JDK 9/10/11: Side Effects from += on Java String

Image
The question " Why does `array[i++%n] += i+" "` give different results in Java 8 and Java 10? " was posted earlier this week on StackOverflow.com . It points to a bug in the Java compiler that is present in JDK 9 and later , but is not present in JDK 8 . As explained on the StackOverflow thread , Didier L provided a simple example of Java code that reproduces this issue. That is adapted in the code listing shown next. package dustin.examples.strings; import static java.lang.System.out; /** * Example demonstrating JDK-8204322 and adapted from Didier L's * original example (https://stackoverflow.com/q/50683786). */ public class StringConcatenationBug { static void didierLDemonstration() { final String[] array = {""}; array[generateArrayIndex()] += "a"; } static int generateArrayIndex() { out.println("Array Index Evaluated"); return 0; } public static void main(final String[] argumen...