Java – Undefined behaviour in Java

cjavaundefined-behavior

I was reading this question on SO which discusses some common undefined behavior in C++, and I wondered: does Java also have undefined behaviour?

If that is the case, then what are some common causes of undefined behaviour in Java?

If not, then which features of Java make it free from such behaviours and why haven't the latest versions of C and C++ been implemented with these properties?

Best Answer

In Java, you can consider behavior of incorrectly synchronized program undefined.

Java 7 JLS uses word "undefined" once, in 17.4.8. Executions and Causality Requirements:

We use f|d to denote the function given by restricting the domain of f to d. For all x in d, f|d(x) = f(x), and for all x not in d, f|d(x) is undefined...

Java API documentation specifies some cases when results are undefined - for example, in (deprecated) constructor Date(int year, int month, int day):

The result is undefined if a given argument is out of bounds...

Javadocs for ExecutorService.invokeAll(Collection) state:

The results of this method are undefined if the given collection is modified while this operation is in progress...

Less formal kind of "undefined" behavior can be found for example in ConcurrentModificationException, where API docs use term "best effort":

Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness...


Appendix

One of the question comments refers to an article by Eric Lippert which provides helpful introduction into topic matters: Implementation-defined behaviour.

I recommend this article for the language-agnostic reasoning, although it is worth keeping in mind that author targets C#, not Java.

Traditionally we say that a programming language idiom has undefined behaviour if use of that idiom can have any effect whatsoever; it can work the way you expect it to or it can erase your hard disk or crash your machine. Moreover, the compiler author is under no obligation to warn you about the undefined behaviour. (And in fact, there are some languages in which programs that use "undefined behaviour" idioms are permitted by the language specification to crash the compiler!)...

By contrast, an idiom that has implementation-defined behaviour is behaviour where the compiler author has several choices about how to implement the feature, and must choose one. As the name implies, implementation-defined behaviour is at least defined. For example, C# permits an implementation to throw an exception or produce a value when an integer division overflows, but the implementation must pick one. It cannot erase your hard disk...

What are some of the factors that lead a language design committee to leave certain language idioms as undefined or implementation-defined behaviours?

The first major factor is: are there two existing implementations of the language in the marketplace that disagree on the behaviour of a particular program? ...

The next major factor is: does the feature naturally present many different possibilities for implementation, some of which are clearly better than others? ...

A third factor is: is the feature so complex that a detailed breakdown of its exact behaviour would be difficult or expensive to specify? ...

A fourth factor is: does the feature impose a high burden on the compiler to analyze? ...

A fifth factor is: does the feature impose a high burden on the runtime environment? ...

A sixth factor is: does making the behaviour defined preclude some major optimization? ...

Those are just a few factors that come to mind; there are of course many, many other factors that language design committees debate before making a feature "implementation defined" or "undefined".

Above is only a very brief coverage; full article contains explanations and examples for the points mentioned in this excerpt; it is much worth reading. For example, details given for the "sixth factor" can give one an insight into motivation for many statements in Java Memory Model (JSR 133), helping to understand why some optimizations are allowed, leading to undefined behavior while others are prohibited, leading to limitations like happen-before and causality requirements.

None of the article materials is particularly new to me but I'll be damned if I ever seen it presented in such an elegant, consise and understandable way. Amazing.