⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 13.doc.html

📁 java语言规范
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<html>
<head>
<title>The Java Language Specification Binary Compatibility</title>
</head>
<body BGCOLOR=#eeeeff text=#000000 LINK=#0000ff VLINK=#000077 ALINK=#ff0000>
 
<a href="index.html">Contents</a> | <a href="12.doc.html">Prev</a> | <a href="14.doc.html">Next</a> | <a href="j.index.doc1.html">Index</a>
<hr><br>
 
<a name="44871"></a>
<p><strong>
CHAPTER 13 </strong></p>
<a name="44872"></a>
<h1>Binary Compatibility</h1>
<hr><p>
<a name="44874"></a>
Java development tools should support automatic recompilation as necessary 
whenever source code is available. Particular implementations of Java may also 
store the source and binary of types in a versioning database and implement a 
<code>ClassLoader</code> <a href="javalang.doc13.html#14462">(&#167;20.14)</a> that uses integrity mechanisms of the database to prevent 
linkage errors by providing binary-compatible versions of types to clients.
<p><a name="44878"></a>
Developers of packages and classes that are to be widely distributed face a different set of problems. In the Internet, which is our favorite example of a widely distributed system, it is often impractical or impossible to automatically recompile the pre-existing binaries that directly or indirectly depend on a type that is to be changed. Instead, Java defines a set of changes that developers are permitted to make to a package or to a class or interface type while preserving (not breaking) compatibility with existing binaries.<p>
<a name="44879"></a>
The paper quoted above appears in <i>Proceedings of OOPSLA '95</i>, published as <i>ACM SIGPLAN Notices</i>, Volume 30, Number 10, October 1995, pages 426-438. Within the framework of that paper, Java binaries are binary (release-to-release) compatible under all relevant transformations that the authors identify. Using their scheme, here is a list of some important binary compatible changes that Java supports:<p>
<ul><a name="44880"></a>
<li>Reimplementing existing methods, constructors, and initializers to improve performance.
<a name="44881"></a>
<li>Changing methods or constructors to return values on inputs for which they previously either threw exceptions that normally should not occur or failed by going into an infinite loop or causing a deadlock.
<a name="44882"></a>
<li>Adding new fields, methods, or constructors to an existing class or interface.
<a name="44883"></a>
<li>Deleting <code>private</code> fields, methods, or constructors of a class or interface.
<a name="44884"></a>
<li>When an entire package is updated, deleting default (package-only) access fields, methods, or constructors of classes and interfaces in the package.
<a name="44885"></a>
<li>Reordering the fields, methods, or constructors in an existing type declaration.
<a name="44886"></a>
<li>Moving a method upward in the class hierarchy, provided a forwarding method is left in its place.
<a name="44887"></a>
<li>Reordering the list of direct superinterfaces of a class or interface.
<a name="44888"></a>
<li>Inserting new class or interface types in the type hierarchy.
</ul><a name="44889"></a>
This chapter specifies minimum standards for binary compatibility guaranteed by all Java implementations. Java guarantees compatibility when binaries of classes and interfaces are mixed that are not known to be from compatible sources, but whose sources have been modified in the compatible ways described here.<p>
<a name="44891"></a>
We encourage Java development systems to provide facilities that alert developers to the impact of changes on pre-existing binaries that cannot be recompiled.<p>
<a name="44892"></a>
This chapter first specifies some properties that any Java binary format must have <a href="13.doc.html#44909">(&#167;13.1)</a>. It next defines binary compatibility, explaining what it is and what it is not <a href="13.doc.html#44952">(&#167;13.2)</a>. It finally enumerates a large set of possible changes to packages <a href="13.doc.html#47338">(&#167;13.3)</a>, classes <a href="13.doc.html#44977">(&#167;13.4)</a> and interfaces <a href="13.doc.html#45337">(&#167;13.5)</a>, specifying which changes are guaranteed to preserve binary compatibility and which are not.<p>
<a name="44909"></a>
<h2>13.1    The Form of a Java Binary</h2>
<a name="44910"></a>
While many Java binary files are likely to be in exactly the <code>class</code> file format specified
by the <i>The Java Virtual Machine Specification</i>, this specification does not 
mandate the use of any specific binary file format. Rather, it specifies properties 
that any binary format for compiled types must obey. A number of these properties
are specifically chosen to support source code transformations that preserve 
binary compatibility.
<p><a name="44911"></a>
The requirements are:<p>
<ul><a name="44912"></a>
<li>Binary formats for Java programs must be defined and processed to respect the specifications of loading <a href="12.doc.html#44459">(&#167;12.2)</a>, linking <a href="12.doc.html#44487">(&#167;12.3)</a> and initialization <a href="12.doc.html#44557">(&#167;12.4)</a> of class and interface types.
<a name="44922"></a>
<li>A reference to another class or interface type must be symbolic, using the fully qualified name of the type as determined at compile time.
<a name="44923"></a>
<li>A reference to a field of another class or interface must be resolved at compile time to a symbolic reference to the class or interface in which the field is declared, plus the simple name of the field. (Including the exact class or interface in which the field is declared makes the binaries more robust, since adding another field with the same name, even in a subclass, cannot cause confusion at link time. This rule does mean, however, that moving a field to a superclass is not a binary compatible change; see <a href="13.doc.html#45037">&#167;13.4.5</a> for a discussion.) The reference must also include a symbolic reference to the declared type of the field so that the verifier can check that the type is as expected. References to fields that are <code>static</code>, <code>final</code>, and initialized with compile-time constant expressions are resolved at compile time to the constant value that is denoted. No reference to such a constant field should be present in the code in a binary file (except in the class or interface containing the constant field, which will have code to initialize it), and such constant fields must always appear to have been initialized; the default initial value for the type of such a field must never be observed. See <a href="13.doc.html#45139">&#167;13.4.8</a> for a discussion.
<a name="44930"></a>
<li>A reference to a method or constructor must be resolved at compile time to a symbolic reference to the class or interface in which the denoted method or constructor is declared, plus the signature of the method or constructor. (As for fields, this makes the binaries more robust, with the caveat that such a method cannot be moved to a superclass without leaving a forwarding method behind; see <a href="13.doc.html#45037">&#167;13.4.5</a> for a discussion.) A reference to a method must also include either a symbolic reference to the return type of the denoted method or an indication that the denoted method is declared <code>void</code> and does not return a value. The signature of a method must include all of the following:
<ul>
<a name="44937"></a>
<li>The simple name of the method
<a name="46201"></a>
<li>The number of parameters to the method 
<a name="46202"></a>
<li>A symbolic reference to the type of each parameter
</ul>
</ul><ul><a name="46994"></a>
<br><br>The signature of a constructor must include both:
<ul>
<a name="46995"></a>
<li>The number of parameters to the constructor
<a name="46996"></a>
<li>A symbolic reference to the type of each parameter
</ul>
</ul><a name="46203"></a>
A Java binary representation for a class or interface must also contain all of the 
following:
<p><ul><a name="44941"></a>
<li>If it is a class and is not class <code>java.lang.Object</code>, then a symbolic reference to the direct superclass of this class
<a name="44942"></a>
<li>A symbolic reference to each direct superinterface, if any
<a name="44943"></a>
<li>A specification of each field that is not <code>private</code> declared in the class or interface, given as the simple name of the field and a symbolic reference to the type of the field
<a name="44944"></a>
<li>If it is a class, then the signature of each constructor, as described above
<a name="44945"></a>
<li>For each method that is not <code>private</code> declared in the class or interface, its signature and return type, as described above
<a name="44946"></a>
<li>The code needed to implement the class or interface:
<ul>
<a name="44947"></a>
<li>For an interface, code for the field initializers
<a name="44948"></a>
<li>For a class, code for the field initializers, the static initializers, and the implementation of each method or constructor that is not declared <code>private</code>
</ul>
</ul><a name="44949"></a>
If a Java system defines a binary format that represents a group of classes and interfaces comprised by an entire package, then this binary format need not expose information about fields, methods, or constructors that are declared with default (package) access.<p>
<a name="44950"></a>
The following sections specify the changes that may be made to class and interface type declarations without breaking compatibility with pre-existing binaries. The Java Virtual Machine and its standard <code>class</code> file format support these changes; other Java binary formats are required to support these changes as well.<p>
<a name="44952"></a>
<h2>13.2    What Binary Compatibility Is and Is Not</h2>
<a name="44953"></a>
A change to a type is <i>binary compatible</i> <i>with</i> (equivalently, does not<i> break binary 
compatibility </i>with) preexisting binaries if preexisting binaries that previously 
linked without error will continue to link without error.
<p><a name="44957"></a>
As described in <a href="13.doc.html#44909">&#167;13.1</a>, symbolic references to methods and fields name the exact class or interface in which the method or field is declared. This means that binaries are compiled to rely on the accessible members and constructors of other classes and interfaces. To preserve binary compatibility, a class or interface should treat these accessible members and constructors, their existence and behavior, as a <i>contract</i> with users of the class or interface.<p>
<a name="44958"></a>
Java is designed to prevent additions to contracts and accidental name collisions from breaking binary compatibility; specifically:<p>
<ul><a name="44959"></a>
<li>Introducing a new field with the same name as an existing field, in a subclass of the class containing the existing field declaration, does not break compatibility with preexisting binaries. See the example at the beginning of <a href="13.doc.html#45037">&#167;13.4.5</a>.
<a name="44963"></a>
<li>Addition of more methods overloading a particular method name does not break compatibility with preexisting binaries. The method signature that the preexisting binary will use for method lookup is chosen by Java's method overload resolution algorithm at compile time <a href="15.doc.html#21693">(&#167;15.11.2)</a>. (If Java had been designed so that the particular method to be executed was chosen at run time, then such an ambiguity might be detected at run time. Such a rule would imply that adding an additional overloaded method so as to make ambiguity possible at a call site became possible could break compatibility with an unknown number of preexisting binaries. See <a href="13.doc.html#45274">&#167;13.4.22</a> for more discussion.)
</ul><a name="44967"></a>
Binary compatibility is not the same as source compatibility. In particular, the example in <a href="13.doc.html#45037">&#167;13.4.5</a> shows that a set of compatible binaries can be produced from sources that will not compile all together. This example is typical: a new declaration is added, changing the meaning of a name in an unchanged part of the source code, while the preexisting binary for that unchanged part of the source code retains the fully-qualified, previous meaning of the name. Producing a consistent set of source code requires providing a qualified name or field access expression corresponding to the previous meaning.<p>
<a name="47335"></a>
We hope to make some improvements to future versions of Java to better support both source and binary compatible evolution of types. In particular, we are considering a mechanism to allow a class to implement two interfaces that have methods with the same signature but are to be considered different or have different return types. We welcome suggestions and proposals that would help us to make additional improvements, either in managing name and signature conflicts or other sources of incompatibility.<p>
<a name="47338"></a>
<h2>13.3    Evolution of Packages</h2>
<a name="44974"></a>
A new class or interface type may be added to a package without breaking compatibility
with pre-existing binaries, provided the new type does not reuse a name 
previously given to an unrelated type. If a new type reuses a name previously 
given to an unrelated type, then a conflict may result, since binaries for both types 
could not be loaded by the same class loader.
<p><a name="44975"></a>
Changes in class and interface types that are not <code>public</code> and that are not a superclass or superinterface, respectively, of a <code>public</code> type, affect only types within the package in which they are declared. Such types may be deleted or otherwise changed, even if incompatibilities are otherwise described here, provided that the affected binaries of that package are updated together.<p>
<a name="44977"></a>
<h2>13.4    Evolution of Classes</h2>
<a name="44978"></a>
This section describes the effects of changes to the declaration of a class and its 
members and constructors on pre-existing binaries.
<p><a name="44980"></a>
<h3>13.4.1    <code>abstract</code> Classes</h3>
<a name="44981"></a>
If a class that was not <code>abstract</code> is changed to be declared <code>abstract</code>, then pre-
existing binaries that attempt to create new instances of that class will throw either 
an <code>InstantiationError</code> at link time, or an <code>InstantiationException</code> at run 
time (if the method <code>newInstance</code> <a href="javalang.doc2.html#15088">(&#167;20.3.6)</a> of class <code>Class</code> is used); such a change 
is therefore not recommended for widely distributed classes.
<p><a name="44985"></a>
Changing a class that was declared <code>abstract</code> to no longer be declared <code>abstract</code> does not break compatibility with pre-existing binaries.<p>
<a name="44987"></a>
<h3>13.4.2    <code>final</code> <code></code>Classes</h3>
<a name="44988"></a>
If a class that was not declared <code>final</code> is changed to be declared <code>final</code>, then a 
<code>VerifyError</code> is thrown if a binary of a pre-existing subclass of this class is 
loaded, because <code>final</code> classes can have no subclasses; such a change is not recommended
for widely distributed classes.
<p><a name="44989"></a>
Changing a class that was declared <code>final</code> to no longer be declared <code>final </code>does not break compatibility with pre-existing binaries.<p>
<a name="44990"></a>
<h3>13.4.3    <code>public</code> <code></code>Classes</h3>
<a name="44991"></a>
Changing a class that was not declared <code>public</code> to be declared <code>public</code> does not 
break compatibility with pre-existing binaries.
<p><a name="44992"></a>
If a class that was declared <code>public</code> is changed to not be declared <code>public</code>, then an <code>IllegalAccessError</code> is thrown if a pre-existing binary is linked that needs but no longer has access to the class type; such a change is not recommended for widely distributed classes.<p>
<a name="44994"></a>
<h3>13.4.4    Superclasses and Superinterfaces</h3>
<a name="44995"></a>
A <code>ClassCircularityError</code> is thrown at load time if a class would be a superclass
of itself. Changes to the class hierarchy that could result in such a circularity 
when newly compiled binaries are loaded with pre-existing binaries are not recommended
for widely distributed classes.
<p><a name="44996"></a>
Changing the direct superclass or the set of direct superinterfaces of a class type will not break compatibility with pre-existing binaries, provided that the total set of superclasses or superinterfaces, respectively, of the class type loses no members.<p>
<a name="44997"></a>
Changes to the set of superclasses of a class will not break compatibility with pre-existing binaries simply because of uses of class variables and class methods. This is because uses of class variables and class methods are resolved at compile time to symbolic references to the name of the class that declares them. Such uses therefore depend only on the continuing existence of the class declaring the variable or method, not on the shape of the class hierarchy.<p>
<a name="44998"></a>
If a change to the direct superclass or the set of direct superinterfaces results in any class or interface no longer being a superclass or superinterface, respectively, then link-time errors may result if pre-existing binaries are loaded with the binary of the modified class. Such changes are not recommended for widely distributed classes. The resulting errors are detected by the verifier of the Java Virtual Machine when an operation that previously compiled would violate the type system. For example, suppose that the following test program:<p>
<pre><a name="44999"></a>class Hyper { char h = 'h'; } 
<a name="45000"></a>class Super extends Hyper { char s = 's'; }
<a name="45001"></a>class Test extends Super {
<a name="45002"></a>    public static void main(String[] args) {
<a name="45003"></a>        Hyper h = new Super();
<a name="45004"></a>        System.out.println(h.h);
<a name="45005"></a>    }
<a name="45006"></a>}
</pre><a name="45007"></a>
is compiled and executed, producing the output:
<p><pre><a name="45008"></a>h
</pre><a name="47239"></a>
Suppose that a new version of class <code>Super</code> is then compiled:
<p><pre><a name="47240"></a>class Super { char s = 's'; }
</pre><a name="47241"></a>
This version of class <code>Super</code> is not a subclass of <code>Hyper</code>. If we then run the existing 
binaries of <code>Hyper</code> and <code>Test</code> with the new version of <code>Super</code>, then a <code>VerifyError</code> 
is thrown at link time. The verifier objects because the result of <code>new</code> <code>Super()</code> 
cannot &#32;be assigned to a variable of type <code>Hyper</code>, because <code>Super</code> is not a subclass of 
<code>Hyper</code>.
<p><a name="45012"></a>
It is instructive to consider what might happen without the verification step: the program might run and print:<p>
<pre><a name="45013"></a>s
</pre><a name="45014"></a>
This demonstrates that without the verifier the type system could be defeated by 
linking inconsistent binary files, even though each was produced by a correct Java 
compiler.
<p><a name="45015"></a>
As a further example, here is an implementation of a cast from a reference type to <code>int</code>, which could be made to run in certain implementations of Java if they failed to perform the verification process. Assume an implementation that uses method dispatch tables and whose linker assigns offsets into those tables in a sequential and straightforward manner. Then suppose that the following Java code is compiled:<p>
<pre><a name="45016"></a>class Hyper { int zero(Object o) { return 0; } }
<a name="45017"></a>class Super extends Hyper { int peek(int i) { return i; }  }
</pre><pre><a name="45018"></a>
class Test extends Super {
<a name="45019"></a>	public static void main(String[] args) throws Throwable {
<a name="45020"></a>		Super as = new Super();
<a name="45021"></a>		System.out.println(as);
<a name="45022"></a>		System.out.println(Integer.toHexString(as.zero(as)));
<a name="45023"></a>	}
<a name="45024"></a>}
</pre><a name="45025"></a>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -