[jmm-dev] safety

Doug Lea dl at cs.oswego.edu
Wed Mar 19 18:57:08 UTC 2014

Here's a paste from John Rose's blog post from a few days ago
that expands on some of the C vs Java differences impacting
memory models we discussed in January. Nothing here should be
surprising, but it includes a couple of minor points not
mentioned in those discussions.



     basic type safety: Pointers, integers, and floats must not be confused; 
conversions must be explicit and must preserve VM integrity. This applies to 
values of all kinds, in memory and elsewhere.

     basic operation safety: Any basic VM operation either completes according 
its specification, or produces a catchable exception. It cannot corrupt memory 
or any other VM state.

     class safety: Pointer conversions must be explicit and checked. There are 
exceptions for conversion to a Java superclass (which is always safe), to a Java 
interface (which is always checked later at any use point), and to an erased 
generic type (which is checked implicitly).

     storage lifetime safety: No block of memory can be accessed after it has 
been deallocated. This is why we have automatic storage management.

     variable domain safety: There is no way to obtain “garbage” or 
indeterminately initialized values of any type (especially pointers, of course).

     API type checking: Every use of an API, such as a method call, is fully 
type-consistent with its definition (such has a method definition). This 
requirement serves the earlier ones, of course; it shows up in detail in the 
operation of Java’s dynamic linkage rules.

     late linking: All uses of names, including class, method, and field names, 
are resolved and access-checked not only at compile time but also at run time. 
Separately compiled modules (classes) cannot observe the implementation details 
of other modules.

     concurrency safety: Race conditions between threads can be prevented, or 
their effects can be predicted usefully, or (at worst) they cannot violate the 
other safety invariants.

     error manifestation: Exceptional or erroneous conditions are not discarded. 
They are manifested as thrown exceptions, which will be caught and/or displayed.

     access control: Non-public or otherwise restricted API points cannot be 
accessed except by their specified users. Access is enforced at all phases of 
compilation and execution. System internals cannot be touched except by highly 
trusted code.

     appropriately concise: Typically, Java code does not pay for any of Java’s 
built-in safety features by unnecessary verbosity. Safe and sane practices are 
encouraged by simpler notations. The “semantic payload” of a bit of code is not 
obscured by any necessary ceremony. (But note next points.)

     predictably explicit: Typically, complex or potentially expensive features 
of Java are made explicit by a visible syntax, such as a method call. (This 
point is in tension with the previous point, and reasonable people differ on the 
proper resolution.)

     explicit types: Java code has reasonably strong static typing, with many 
types explicitly written in the source code. (Notably, declaration types are 
explicit on the left, despite type inference elsewhere.) This feature catches 
errors early and gives IDEs helpful context for each name.

     transparent code: Programs are represented using bytecode, which automated 
tools can inspect, verify, and transform. User-written annotations can help 
guide these tasks. There are easy to use, open source implementations of offline 
processors for both source code and bytecode, as well as the VM itself. Multiple 
good IDEs exist.

     transparent data: Data can be inspected using reflection and other 
ubiquitous self-description machinery such as toString and debuggers. 
(Transparency of data is balanced with access control, of course.)

     robust performance: With moderate programmer care and experience, simple 
single-threaded programs tend to not show surprising performance “potholes”, not 
even when they are composed together. Multi-threaded programs preserve and scale 
up throughput with additional CPUs, in the absence of algorithmic bottlenecks.

More information about the jmm-dev mailing list