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
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
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