Dynamics of Java Programming, Part 1: Class and class loading

zhaozj2021-02-12  169

(There is a reduction)

The level of cases occurring when researching and JVM loading: Intermediate

Dennis M. Sosnoski (DMS@sosnoski.com)

President, Sosnoski Software Solutions, Inc. 2003 June

Loading classes such as C and C These compilation cost machine code are usually required to link this step after compiling the completed source code. This link process combines the code and shared library code from independent compilation of the individual source files to form an executable program. The Java language is different. Using the Java language, the class generated by the compiler is usually maintained before being loaded into the JVM. Even if you build JAR files from class files, this is not changed - JAR is just a container of class files.

The link class is not a stand-alone step, which is part of the JVM to load these classes to memory. This step will increase some overhead when the class is initially loaded, but it also provides high flexibility for Java applications. For example, the actual implementation can be specified when writing an application to run when using an interface. This post-associated method for assembling the application is widely used in the Java platform. Servlet is a common example.

The rules of the load class are described in detail in the JVM specification. Its basic principle is that it is only loaded only when needed (or at least looks like this - JVM has some flexibility in actual loading, but must maintain a fixed class initialization order). Each loaded class may have other dependencies, so the loading process is recursive. The class in Listing 2 shows this recursive load mode. The Demo class contains a simple main method that creates a GREETER instance and calls the GREET method. The GREETER constructor creates an instance of a message and then uses it in the Greet method call.

Listing 2. Source code loaded in the presentation PUBLIC CLASS DEMO {public static void main (String [] args) {system.out.println ("** beginning execution **"); Greter Greter = new Greter (); system .out.println ("** created Greter **"); GREETER.GREET ();}}

Public Class Greter {private static message s_message = new message ("Hello, World!"); public void greet () {s_message.print (system.out);}}

Public class message {private string m_text; public message (string text) {m_text = text;} public void print (java.io.printStream ps) {ps.println (m_text);}}

Setting the parameters on the Java command line -verbose: Class prints the tracking record of the class load process. Listing 3 shows some of the outputs of the list of procedures using this parameter:

Listing 3. -verbose: Part of the output of CLASS

[Opened /usR/JAVA/J2SDK1.4.1/jre/lib/rt.jar][pened /usr/java/j2sdk1.4.1/jre/lib/sunrsasign.jar][pened /usr/java/j2sdk1.4.1/jre /LIB/JSSE.jar][pened /usr/java/j2sdk1.4.1/jre/lib/jce.jar][pened /usr/java/j2sdk1.4.1/jre/lib/charsets.jar][loaded java.lang .Object from /usr/java/j2sdk1.4.1/jre/lib/rt.jar][loaded java.io.serializable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar][loaded java.lang . Comparable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar][loaded java.lang.charsequence from /usr/java/j2sdk1.4.1/jre/lib/rt.jar][loaded java.lang . String from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]...[Loaded java.security.principal from /usr/java/j2sdk1.4.1/jre/lib/rt.jar][loaded Java.security.cert.certificate from /usr/java/j2sdk1.4.1/jre/lib/rt.jar][loaded demo] ** beginning execution ** [loaded Greter] [loaded message] ** created Greter ** Hello , World! [Loaded java.util.hashmap $ Keyset from /usr/java/j2sdk1.4.1/jre/lib/rt.jar][Loaded Java.util.hashmap $ Keeiiterator from /usr/java/j2sdk1.4.1/jre /LIB/rt.jar] This listing The most important part of the output - complete tracking record consists of 294 lines, I deleted most of them, forming this list. The initial set of layers (279 in this case) are triggered when trying to load the Demo class. These classes are the core classes to be used every Java program (regardless of how small). Even if all code to delete the Demo Main method does not affect this initial loading order. However, the number and name involved in different versions of the class library are different.

In this list, some of the part after loading the Demo class is more interesting. The order here shows that the class is only loaded when you are ready to create a Greter class. However, the Greter class uses a static instance of the Message class, so you must first load the Message class before you can create an instance of the GREETER class.

When loading and initialization, the JVM will complete a number of operations, including decoding binary classes, checking compatibility with other classes, verifying the order of the bytecode operation, and final constructing java.lang.class instances to represent new classes. This Class object has become the basis for all instances of JVM creation. It is still loaded into the identity of the class - for the same binary class loaded into the JVM, there can be multiple copies, each copy has its own Class instance. Even if these copies share the same class name, they are independent classes for JVM.

Unconventional (class) path is loaded into the JVM is controlled by class loader. A boot program class loader is built in JVM, which is responsible for loading basic Java class library classes. This special type of equipment has some specializes. First, it is only loaded into the class found on the boot type path. Because these are trusted system classes, the boot program is skipped over a large number of verifications made to regular (untrusted) classes. The bootstrap is not a unique class loader. For beginners, JVM defines an extended class loader for classes in the Loading Standard Java Extended API, and defines a system class loader for classes (including application classes) on the general class path. . Applications can also define their own type of equipment for special purposes (eg, reloading). This add-to-enumerator is derived from a Java.lang.ClassLoader class (which may be indirectly derived), which provides core support for building internal classes from byte arrays (java.lang.class instance). Each construction class is "owned" by loading its class equipment in a sense. Class loaders typically retain their mounted mappings, so that this class can be found by name when a class is requested again.

Each class loader also retains a reference to the parental loader, which defines a class loader tree, and the root is the bootstrap loader. When a particular class instance (identified by the name), no matter which type of loader initially processes the request, it is generally checked for the parental loader before attempting to load the class directly. If there is a multi-layer loader, it will be recursively implemented, so this means that it is usually visible not only in the type of equipment that is loaded into the class, but also for all future renewers are also visible. This also means that if there are multiple type loaders on a chain to be loaded into a class, then the one of the most upper ends of the tree is the type of equipment that actually loads the class.

In many environments, the Java program uses multiple application class loaders. The J2EE framework is an example. Each J2EE application that the frame is loaded needs to have a separate class equipment to prevent classes in an application to interfere with other applications. The frame code itself will also use one or more other types of equipment, which is also used to prevent interference from the application or from the application. The entire type of loader sets the hierarchy of the tree structure, which can be loaded with different types of classes at each level.

The loader tree is an actual example of the type of type assembler hierarchy, and Fig. 1 shows the class equipment hierarchy defined by the Tomcat Servlet Engine. Here the CommON class loader is loaded from a JAR file for a particular directory installed in Tomcat to intend to share code between servers and all WEB applications. The Catalina loader is used to load Tomcat's own class, while the Shared loader is used to load the class shared between the web application. Finally, each web application has its own loader for its private class.

Figure 1. Tomcat type loader

In this environment, tracking the appropriate loader for requesting new category is very confusing. To do this, add the setContextClassLoader method and the getContextClassLoader method in the Java 2 platform to the java.lang.thread class. These methods allow the frame to set the type of loader such that the class loader can be used for the application when running the code in each application.

This flexibility that can be loaded into independent class is an important feature of the Java platform. Although this feature is useful, it will be confused in some cases. A confusing aspect is the old problem such as the JVM class path. For example, in the TOMCAT type mounted hierarchy displayed in Figure 1, the class that is loaded by the COMMON class loader (according to the name) is directly accessed by the web application. The only way to link these classes is by using the interfaces visible in these two classs. In this example, it is a javax.servlet.servlet that is implemented by Java Servlet. No matter what reason, there will be problems when moving the code between the type loaders. For example, when J2SE 1.4 moves the JAXP API for XML processing to a standard distribution, there is a problem in many environments, as applications in these environments are previously depends on the XML API implementation that is loaded into them. of. Using J2SE 1.3, you can solve this problem as long as you contain the appropriate JAR file in the user class path. In J2SE 1.4, these APIs are now located in the extended classpath, so they usually override any implementations that appear in the user path.

Using multiple types of loaders may also cause other types of confusion. Figure 2 shows an example of a class identity crisis, which is a crisis generated when two independent loaders are loaded into an interface and their related implementations. Even if the names and binary implementations of the interfaces and classes are the same, the instance from a class from one loader cannot be considered to implement an interface from another loader. This confusion can be relieved by moving the interface class I to the SYSTEM class loader. Class A still has two independent instances, but they all achieve the same interface I.

Figure 2. Class identity crisis

Conclusion Java class definitions and JVM specifications are unfunctional framework for runtime assembly code. By using a class loader, a Java application can use multiple versions of classes, otherwise these classes will cause conflicts. The flexibility of the type of assembly even allows dynamically reloading the modified code, while the application continues.

Here, the Java platform flexibility is to some extent to start the expenditure of the application as the price. Before the JVM can start executing or even the simplest application code, it must be loaded with hundreds of separate classes. This start-up cost is usually more suitable for long-running server type applications for frequently used applets. Server applications also benefit from code to assemble this flexibility at runtime, so the Java platform is increasingly favored for this development.

In Part 2 of this series, I will introduce another aspect of the dynamic foundation of the Java platform: Reflecting the API (REFLECTION API). Reflection enables execution code to access internal information. This may be a great tool to build a flexible code, you can hill the code together when any source code link is not used. But like most tools, you must know when and how to use it for maximum benefit. Please read the Dynamics of Java Programming Part 2 to understand the effective reflection.

Reference

Direct to the Java Virtual Machine Specification to understand the details of binary formats, classes, and actual Java bytecodes. Read the tutorial prepared by Greg Travis "Understanding Java ClassLoader" (DeveloperWorks, April 2001) Understand all details of building your own special type loader. MARTYN Honeyford is popular "Measure Java Native Compilation" article (United States, Jan 201) provides more details on Java Language Code Compilation and Probability. The binary format contains a lot of important information, usually this information is even enough to restructive source code (except for annotations). In Greg Travis's "HOWEEN UPSEONE ELSE's" article (developerWorks, May 2001), he shows you how to use this information. Get detail about Jikes Research Virtual Machine (RVM), which is implemented in Java language and is self-managed (ie, its Java code is running itself, no need for another virtual machine). Request 175 (Java Specification Request 175, JSR 175) with Java Specification Request 175, Java Programming Language, which is closely to the development of the property for Java developers. Understand the details of the Apache Software Foundation of the Apache Tomcat Java Language Web Server project, including the details of the Tomcat type loader usage. Hundreds of Java Technical References can be found in the developerWorks Java technology area. About the author Dennis Sosnoski is the founder and Chief Consultant of Sosnoski Software Solutions, Inc., Seattle Region, is an expert in J2EE, XML and Web service support. He has more than 30 years of professional software development experience, and he concentrates on the Java technology of the server in recent years. Dennis often speaking on XML and Java technology at a national meeting, he is a chairman of Seattle Java-XML Sig. You can contact Dennis via DMS@sosnoski.com.

转载请注明原文地址:https://www.9cbs.com/read-6924.html

New Post(0)