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

📄 chap05.html

📁 Inside the java virtualMachine,深入研究java虚拟机
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<P>As mentioned in Chapter 1, the Java Virtual Machine contains two kinds of class loaders: a <I>primordial class loader</I> and <I>class loader objects</I>. The primordial class loader is a part of the virtual machine implementation, and class loader objects are part of the running Java application. Classes loaded by different class loaders are placed into separate <I>name spaces</I> inside the Java Virtual Machine.</P>
<P>The class loader subsystem involves many other parts of the Java Virtual Machine and several classes from the <FONT FACE="Courier New">java.lang</FONT> library. For example, class loader objects are regular Java objects whose class descends from <FONT FACE="Courier New">java.lang.ClassLoader</FONT>. The methods of class <FONT FACE="Courier New">ClassLoader</FONT> allow Java applications to access the virtual machine韘 class loading machinery. Also, for every type a Java Virtual Machine loads, it creates an instance of class <FONT FACE="Courier New">java.lang.Class</FONT> to represent that type. Like all objects, class loader objects and instances of class <FONT FACE="Courier New">Class</FONT> reside on the heap. Data for loaded types resides in the method area.</P>
<I><P>Loading, Linking and Initialization</P>
</I><P>The class loader subsystem is responsible for more than just locating and importing the binary data for classes. It must also verify the correctness of imported classes, allocate and initialize memory for class variables, and assist in the resolution of symbolic references. These activities are performed in a strict order:</P>
<OL><LI>Loading: finding and importing the binary data for a type</P>
<LI>Linking: performing verification, preparation, and (optionally) resolution</P>
<UL>a. Verification: ensuring the correctness of the imported type</P>
b. Preparation: allocating memory for class variables and initializing the memory to default values</P>
c. Resolution: transforming symbolic references from the type into direct references.</P></OL>
<LI>Initialization: invoking Java code that initializes class variables to their proper starting values.</OL>
<P>The details of these processes are given Chapter 7, &quot;The Lifetime of a Class.&quot;</P>
<I><P>The Primordial Class Loader</P>
</I><P>Java Virtual Machine implementations must be able to recognize and load classes and interfaces stored in binary files that conform to the Java class file format. An implementation is free to recognize other binary forms besides class files, but it must recognize class files. One example of an alternative binary format recognized by a particular Java Virtual Machine implementation is the CAB file. This file format, which is an archive of class files and other data files, is defined by Microsoft and recognized by their implementation of the Java Virtual Machine.</P>
<P>Every Java Virtual Machine implementation has a primordial class loader, which knows how to load trusted classes, including the classes of the Java API. The Java Virtual Machine specification doesn韙 define how the primordial loader should locate classes. That is another decision the specification leaves to implementation designers.</P>
<P>Given a fully qualified type name, the primordial class loader must <I>in some way</I> attempt to locate a file with the type韘 simple name plus &quot;<FONT FACE="Courier New">.class</FONT>&quot;. One common approach is demonstrated by the Java Virtual Machine implementation in Sun韘 1.1 JDK on Windows95. This implementation searches a user-defined directory path stored in an environment variable named <FONT FACE="Courier New">CLASSPATH</FONT>. The primordial loader looks in each directory, in the order the directories appear in the <FONT FACE="Courier New">CLASSPATH</FONT>, until it finds a file with the appropriate name: the type韘 simple name plus &quot;<FONT FACE="Courier New">.class</FONT>&quot;. Unless the type is part of the unnamed package, the primordial loader expects the file to be in a subdirectory of one the directories in the <FONT FACE="Courier New">CLASSPATH</FONT>. The path name of the subdirectory is built from the package name of the type. For example, if the primordial class loader is searching for class <FONT FACE="Courier New">java.lang.Object</FONT>, it will look for <FONT FACE="Courier New">Object.class</FONT> in the <FONT FACE="Courier New">java\lang</FONT> subdirectory of each <FONT FACE="Courier New">CLASSPATH</FONT> directory.</P>
<I><P>Class Loader Objects</P>
</I><P>Although class loader objects themselves are part of the Java application, three of the methods in class <FONT FACE="Courier New">ClassLoader</FONT> are gateways into the Java Virtual Machine:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT FACE="Courier New"><P>// Three of the methods declared in class java.lang.ClassLoader:</P>
<P>protected final Class defineClass(byte data[], int offset,</P>
<P>    int length);</P>
<P>protected final Class findSystemClass(String name);</P>
<P>protected final void resolveClass(Class c);</P>
</FONT><P><FONT FACE="Courier New">end</FONT></P></PRE>
<P>Any Java Virtual Machine implementation must take care to connect these methods of class <FONT FACE="Courier New">ClassLoader</FONT> to the internal class loader subsystem. </P>
<P>The <FONT FACE="Courier New">defineClass()</FONT> method accepts a <FONT FACE="Courier New">byte</FONT> array, <FONT FACE="Courier New">data[]</FONT>, as input. Starting at position <FONT FACE="Courier New">offset</FONT> in the array and continuing for <FONT FACE="Courier New">length</FONT> bytes, class <FONT FACE="Courier New">ClassLoader</FONT> expects binary data conforming to the Java class file format--binary data that represents a new type for the running application. Every Java Virtual Machine implementation must make sure the <FONT FACE="Courier New">defineClass()</FONT> method of class <FONT FACE="Courier New">ClassLoader</FONT> can cause a new type to be imported into the method area.</P>
<P>The <FONT FACE="Courier New">findSystemClass()</FONT> method accepts a <FONT FACE="Courier New">String</FONT> representing a fully qualified name of a type. When a class loader object invokes this method, it is requesting that the virtual machine attempt to load the named type via its primordial class loader. If the primordial class loader has already loaded or successfully loads the type, it returns a reference to the <FONT FACE="Courier New">Class</FONT> object representing the type. If it can韙 locate the binary data for the type, it throws <FONT FACE="Courier New">ClassNotFoundException</FONT>. Every Java Virtual Machine implementation must make sure the <FONT FACE="Courier New">findSystemClass()</FONT> method can invoke the primordial class loader in this way.</P>
<P>The <FONT FACE="Courier New">resolveClass()</FONT> method accepts a reference to a <FONT FACE="Courier New">Class</FONT> instance. This method causes the type represented by the <FONT FACE="Courier New">Class</FONT> instance to be linked and initialized (if it hasn韙 already been linked and initialized). The <FONT FACE="Courier New">defineClass()</FONT> method, described above, only takes care of loading. (See the above section, &quot;Loading, Linking, and Initialization&quot; for definitions of these terms.) When <FONT FACE="Courier New">defineClass()</FONT> returns a <FONT FACE="Courier New">Class</FONT> instance, the binary file for the type has definitely been located and imported into the method area, but not necessarily linked and initialized. Java Virtual Machine implementations make sure the <FONT FACE="Courier New">resolveClass()</FONT> method of class <FONT FACE="Courier New">ClassLoader</FONT> can cause the class loader subsystem to perform linking and initialization.</P>
<P>The details of how a Java Virtual Machine performs class loading, linking, and initialization, with class loader objects is given in Chapter 8, &quot;The Linking Model.&quot;</P>
<I><P>Name Spaces</P>
</I><P>As mentioned in Chapter 3, &quot;Security,&quot; each class loader maintains its own name space populated by the types it has loaded. Because each class loader has its own name space, a single Java application can load multiple types with the same fully qualified name. A type韘 fully qualified name, therefore, is not always enough to uniquely identify it inside a Java Virtual Machine instance. If multiple types of that same name have been loaded into different name spaces, the identity of the class loader that loaded the type (the identity of the name space it is in) will also be needed to uniquely identify that type.</P>
<P>Name spaces arise inside a Java Virtual Machine instance as a result of the process of resolution. As part of the data for each loaded type, the Java Virtual Machine keeps track of the class loader that imported the type. When the virtual machine needs to resolve a symbolic reference from one class to another, it requests the referenced class from the same class loader that loaded the referencing class. This process is described in detail in Chapter 8, &quot;The Linking Model.&quot;</P>
<H3><P>The Method Area</P>
</H3><P>Inside a Java Virtual Machine instance, information about loaded types is stored in a logical area of memory called the method area. When the Java Virtual Machine loads a type, it uses a class loader to locate the appropriate class file. The class loader reads in the class file--a linear stream of binary data--and passes it to the virtual machine. The virtual machine extracts information about the type from the binary data and stores the information in the method area. Memory for class (static) variables declared in the class is also taken from the method area.</P>
<P>The manner in which a Java Virtual Machine implementation represents type information internally is a decision of the implementation designer. For example, multi-byte quantities in class files are stored in big-endian (most significant byte first) order. When the data is imported into the method area, however, a virtual machine can store the data in any manner. If an implementation sits on top of a little-endian processor, the designers may decide to store multi-byte values in the method area in little-endian order.</P>
<P>The virtual machine will search through and use the type information stored in the method area as it executes the application it is hosting. Designers must attempt to devise data structures that will facilitate speedy execution of the Java application, but must also think of compactness. If designing an implementation that will operate under low memory constraints, designers may decide to trade off some execution speed in favor of compactness. If designing an implementation that will run on a virtual memory system, on the other hand, designers may decide to store redundant information in the method area to facilitate execution speed. (If the underlying host doesn韙 offer virtual memory, but does offer a hard disk, designers could create their own virtual memory system as part of their implementation.) Designers can choose whatever data structures and organization they feel optimize their implementations performance, in the context of its requirements.</P>
<P>All threads share the same method area, so access to the method area韘 data structures must be designed to be thread-safe. If two threads are attempting to find a class named <FONT FACE="Courier New">Lava</FONT>, for example, and <FONT FACE="Courier New">Lava</FONT> has not yet been loaded, only one thread should be allowed to load it while the other one waits.</P>
<P>The size of the method area need not be fixed. As the Java application runs, the virtual machine can expand and contract the method area to fit the application韘 needs. Also, the memory of the method area need not be contiguous. It could be allocated on a heap--even on the virtual machine韘 own heap. Implementations may allow users or programmers to specify an initial size for the method area, as well as a maximum or minimum size.</P>
<P>The method area can also be garbage collected. Because Java programs can be dynamically extended via class loader objects, classes can become &quot;unreferenced&quot; by the application. If a class becomes unreferenced, a Java Virtual Machine can unload the class (garbage collect it) to keep the memory occupied by the method area at a minimum. The unloading of classes--including the conditions under which a class can become &quot;unreferenced&quot;--is described in Chapter 7, &quot;The Lifetime of a Class.&quot;</P>
<I><P>Type Information</P>
</I><P>For each type it loads, a Java Virtual Machine must store the following kinds of information in the method area:</P>
<UL><LI> The fully qualified name of the type
<LI> The fully qualified name of the type韘 direct superclass (unless the type is an interface or class <FONT FACE="Courier New">java.lang.Object</FONT>, neither of which have a superclass)
<LI> Whether or not the type is a class or an interface
<LI> The type韘 modifiers ( some subset of` <FONT FACE="Courier New">public</FONT>, <FONT FACE="Courier New">abstract</FONT>, <FONT FACE="Courier New">final</FONT>)
<LI> An ordered list of the fully qualified names of any direct superinterfaces</UL>
<P>Inside the Java class file and Java Virtual Machine, type names are always stored as <I>fully qualified names</I>. In Java source code, a fully qualified name is the name of a type韘 package, plus a dot, plus the type韘 <I>simple name</I>. For example, the fully qualified name of class <FONT FACE="Courier New">Object</FONT> in package <FONT FACE="Courier New">java.lang</FONT> is <FONT FACE="Courier New">java.lang.Object</FONT>. In class files, the dots are replaced by slashes, as in <FONT FACE="Courier New">java/lang/Object</FONT>. In the method area, fully qualified names can be represented in whatever form and data structures a designer chooses.</P>
<P>In addition to the basic type information listed above, the virtual machine must also store for each loaded type:</P>
<UL><LI> The constant pool for the type
<LI> Field information
<LI> Method information
<LI> All class (static) variables declared in the type, except constants
<LI> A reference to class <FONT FACE="Courier New">ClassLoader</FONT>
<LI> A reference to class <FONT FACE="Courier New">Class</FONT>
<P>This data is described in the following sections.</UL>
<I><P>The Constant Pool</P>

⌨️ 快捷键说明

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