毕业设计外文文献—Java虚拟机中的动态类加载.docx
附录A外文翻译一原文局部Source: DynamicClass Loading in the Java VirtualMachine Jj.Author: Sheng Liang Gilad Bracha.Dynamic Class Loading in the Java Virtual MachineClass loaders are a powerful mechanism for dynamically loading software components on the Java platform. They are unusual in supporting all of the following features: laziness, type-safe linkage, user-defined extensibility, and multiple communicating namespaces.We present the notion of class loaders and demonstrate some of their interesting uses. In addition, we discuss how to maintain type safety in the presence of user-defined dynamic class loading.In this paper, we investigate an important feature of the Java virtual machine: dynamic class loading. This is the underlying mechanism that provides much of the power of the Java platform: the ability to install software components at runtime. An example of a component is an applet that is downloaded into a web browser.While many other systems16 13 also support some form of dynamic loading and linking, the Java platform is the only system we know of that incorporates all of the following features:1. Lazy loading. Classes are loaded on demand. Class loading is delayed as long as possible, reducing memory usage and improving system response time.2. Type-safe linkage. Dynamic class loading must not violate the type safety of the Java virtual machine. Dynamic loading must not require additional run-time checks in order to guarantee type safety. Additional link-time checks are acceptable, because these checks are performed only once.3. User-definable class loading policy. Class loaders are first-class objects. Programmers have complete control of dynamic class loading. A user-defined class loader can, for example, specify the remote location from which the classes are loaded, or assign appropriate security attributes to classes loaded from a particular source.4. Multiple namespaces. Class loaders provide separate namespaces for different software components. For example, the HotjavaTM browser loads applets from different sources into separate class loaders.These applets may contain classes of the same name, but the classes are treated as distinct types by 此,所有系统类都在applet和应用程序之间共享。这是可取的,因为例 如,如果applet和系统代码具有类型的不同概念,那么会 违反类型安全性。委托类加载器允许我们在共享一组公共类时保持名称空间别离。在 Java虚拟机中,类类型由类名和类加载器的组合唯一确定。Applet和应 用程序类加载器委托给系统类加载器。这可以保证所有系统类类型都是 唯一的。另一方面,一个名为 在applet 1中加载的被认为是与叩plet 2 中命名的类不同的类型。 虽然这两个类具有相同的名称,但它们由不 同的类加载器定义。实际上,这两个类可以完全不相关。例如,它们可 能具有不同的方法或字段。来自一个applet的类不能干扰另一个applet中的类,因为applet被加 载到单独的类加载器中。这对于保证Java平台安全性至关重要。同样, 因为浏览器驻留在单独的类加载器中,所以叩plet无法访问用于实现浏 览器的类。Applet仅允许访问系统类中公开的标准Java API。Java虚拟 机通过创立应用程序类加载器并使用它来加载初始浏览器类来启动。应 用程序执行从初始类的公共类方法开始。调用此方法会驱动所有进一步 的执行。执行指令可能会导致加载其他类。在此应用程序中,浏览器还 为下载的applet创立其他类加载器。垃圾收集器卸载不再引用的applet类。每个类对象都包含对其定义 加载器的引用;每个类加载器都引用它定义的所有类。这意味着,从垃圾 收集器的角度来看,类与它们的定义加载器紧密相关。当定义的加载器 被垃圾收集时,将卸载类。我们现在逐步实现一个简单的类加载器。如前所述,所有用户定义的 类加载器类都是其子类.子类可以覆盖loadClass的定义,从而提供用户定 义的加载策略。公共构造函数MyClassLoader ()只记录目录名称。在loadClass的定 义中,我们使用findLoadedClass方法来检查该类是否已被加载。(4.1节 将给出findLoadedClass方法的更精确描述。)如果ndLoadedClass返回null, 那么尚未加载该类。然后我们通过调用findSystemClass委托给系统类加载 器。如果我们尝试加载的类不是系统类,我们调用一个帮助方法 getClassData来读取类文件。在我们读入类文件之后,我们将它传递给deneClass方法。deneClass方法 从类文件构造类的运行时表示。请注意,10adelass方法在类加载器对象上 同步,以便多个线程可能不会同时加载同一个类。oldoldServer通常需要升级长时间运行的应用程序(如服务器)中的软件组件。 升级不得要求应用程序关闭并重新启动。在Java平台上,此功能转换为重新加载已在正在运行的虚拟机中加 载的类的子集。它对应于模式演化3问题,一般来说可能很难解决。以 下是一些困难:可能有活动对象是我们要重新加载的类的实例。必须迁移这些对象 以符合新类的模式。例如,如果类的新版本包含一组不同的实例字段, 我们必须以某种方式将现有的实例字段值映射到新版本类中的字段。类似地,我们可能必须将静态字段值映射到类的重新加载版本中的 一组不同的静态字段。应用程序可能正在执行属于我们要重新加载的类的方法。我们在本文中没有解决这些问题。相反,我们展示了有时可以使用 类加载器绕过它们。通过在单独的类加载器中组织软件组件,程序员通 常可以防止处理模式演变。相反,新类由单独的加载器加载。图3说明了 Server类如何将服务请求动态重定向到新版本的Service 类。关键技术是将服务器类,旧服务类和新服务类加载到单独的类加载 器中。例如,我们可以使用上一节中介绍的MyClassLoader类来定义 Server oServer.processRequest方法将所有传入请求重定向到存储在私有字段 中的Service对象。它使用Java Core Reflection API 9来调用服务对象上 的“run”方法。此外,Server.updateService方法允许动态加载新版本的 Service类,从而替换现有的服务对象。updateService的调用者提供新类 文件的位置。进一步的请求将被重定向到服务引用的新对象。Server类解析对Service类的符号引用后,它将包含指向该类类型的 硬链接。无法更改已解析的引用。对于从类加载器返回的新版本的 Service, S erver. updates er v ice方法的最后一行中的类型转换将失败。通过接口调度通常比反射更有效。不能重新加载接口类型本身,因 为 Server 类只能引用一个 Serviceinterface 类型。getServiceClass 方法必 须返回一个lass,每次都实现相同的Serviceinterfaceothe Java virtual machine.In contrast, existing dynamic linking mechanisms do not support all of these features. Although most operating systems support some form of dynamic linked libraries, such mechanisms are targeted toward C/C+ code, and are not type-safe. Dynamic languages such as Lisp 13, Smalltalk 6, and Self 21 achieve type safety through additional run-time checks, not link-time checks.The main contribution of this paper is to provide the first in-depth description of class loaders, a novel concept introduced by the Java platform. Class loaders existed in the first version of the Java Development Kit (JDK 1.0). The original purpose was to enable applet class loading in the Hotjava browser. Since that time, the use of class loaders has been extended to handle a wider range of software components such as server-side components (servlets) 11, extensions 10 to the Java platform, and JavaBeans 8 components. Despite the increasingly important role of class loaders, the underlying mechanism has not been adequately described in the literature.A further contribution of this paper is to present a solution to the longstanding type safety problem 20 with class loaders. Early versions (1.0 and 1.1) of the JDK contained a serious flaw in class loader implementation. Improperly written class loaders could defeat the type safety guarantee of the Java virtual machine. Note that the type safety problem did not impose any immediate security risks, because untrusted code (such as a downloaded applet) was not allowed to create class loaders. Nonetheless, application programmers who had the need to write custom class loaders could compromise type safety inadvertently. Although the issue had been known for some time, it remained an open problem in the research community whether a satisfactory solution exists. For example, earlier discussions centered around whether the lack of type safety was a fundamental imitation of user-definable class loaders, and whether we would have to limit the power of class loaders, give up lazy class loading, or introduce additional dynamic type-checking at runtime. The solution we present in this paper, which has been implemented in JDK 1.2, solves the type safety problem while preserving all of the other desirable features of class loaders.We assume the reader has basic knowledge of the Java programming language 7. The remainder of this paper is organized as follows: We first give a more detailed introduction to class loaders. Applications of class loadersare discussed in section 3. Section 4 describes the type safety problems that may arise due to the use of class loaders, and their solutions. Section 5 relates our work to other research. Finally, we present our conclusions in section 6.The purpose of class loaders is to support dynamic loading of software components on the Java platform. The unit of software distribution is a class 1 Classes are distributed using a machine-independent, standard, binary representation known as the class file format 15. The representation of an individual class is referred to as a class file. Class files are produced by Java compilers, and can be loaded into any Java virtual machine. A class file does not have to be stored in an actual file; it could be stored in a memory buffer, or obtained from a network stream.The class file representingcontains a symbolic reference to class Symbolic references are resolved at link time to actual class types. Class types are reified first-class objects in the Java virtual machine. A class type is represented in user code as an object of class.In order to resolve a symbolic reference to a class, the Java virtual machine must load the class file and create the class type.The Java virtual machine uses class loaders to load class files and create class objects.Class loaders are ordinary objects that can be defined in Java code. They are instances of subclasses of the class , shown in Figure l.We have omitted the methods that are not directly relevant to this presentation. The method takes a class name as argument, and returns a object that is the run-time representation of a class type.The methods and will be described later.In the above example, assume that is loaded by the class loader .is referred to as's defining loader. The Java virtual machine will use to load classes referenced by Before the virtual machine allocates an object of class , it must resolve the reference to If has not yet been loaded,the virtual machine will invoke the method of's class loader,to loadApplet class loadersS> stem classes(e.g.java.Iang.String)Application class loaderSvstem class loader JBrowser codeA Java application may use several different kinds of class loaders to manage various software components. For example, Figure 2 shows how a web browser written in Java may use class loaders.This example illustrates the use of two types of class loaders: user-defined class loaders and the system class loader supplied by the Java virtual machine. User-defined class loaders can be used to create classes that originate from user-defined sources. For example, the browser application creates class loaders for downloaded applets. We use a separate class loader for the web browser application itself.All system classes (such as ) are loaded into the system class loader. The system class loader is supported directly by the Java virtual machine.The arrows in the figure indicate the delegation relationship between class loaders. A class loader can ask another loader to load a class on its behalf. In such a case, LI delegates C to L2. For example, applet and application class loaders delegate all system classes to the system class loader.As a result, all system classes are shared among the applets and the application. This is desirable because type safety would be violated if, for example, applet and system code had a different notion of what the type java.lang.String was.Delegating class loaders allow us to maintain namespace separation while still sharing a common set of classes. In the Java virtual machine, a class type is uniquely determined by the combination of the class name and class loader. Applet and application class loaders delegate to the system class loader. This guarantees that all system class types, such as, are unique. On the other hand, a class named loaded in applet 1 is considered a different type from a class named in applet 2. Although these two classes have the same name, they are defined by different class loaders. In fact, these two classes can be completely unrelated. For example, they may have different methods or fields.Classes from one applet cannot interfere with classes in another, because applets are loaded in separate class loaders. This is crucial in guaranteeing Java platform security. Likewise, because the browser resides in a separate class loader, applets cannot access the classes used to implement the browser. Applets are only allowed to access the standard Java API exposed in the system classes. The Java virtual machine starts up by creating the application class loader and using it to load the initial browser class. Application execution starts in the public class method of the initial class. The invocation of thismethod drives all further execution. Execution of instructions may cause loading of additional classes. In this application, the browser also creates additional class loaders for downloaded applets.The garbage collector unloads applet classes that are no longer referenced. Each class object contains a reference to its defining loader; each class loader refers to all the classes it defines. This means that, from the garbage collector's point of view, classes are strongly connected with their defining loader. Classes are unloaded when their defining loader is garbage-collected.We now walk through the implementation of a simple class loader. As noted earlier, all user-defined class loader classes are subclasses of . Subclasses of can override the definition of loadClass, thus providing a userdefined loading policy.The public constructor MyClassLoader() simply records the directory name. In the definition of loadClass, we use the findLoadedClass method to check whether the class has already been loaded. (Section 4.1 will give a more precise description of the findLoadedClass method.) If ndLoadedClass returns null, the class has not yet been loaded. We then delegate to the system class loader by calling findSystemClass. If the class we are trying to load is not a system class, we call a helper method getClassData to read in the class file.After we have read in the class file, we pass it to the deneClass method. The deneClass method constructs the run-time representation of the class from the class file. Note that the loadClass method synchronizes on the class loader object so that multiple threads may not load the same class at the same time.ServerServerIt is often desirable to upgrade software components in a long-running application such as a server. The upgrade must not require the application to shut down and restart.On the Java platform, this ability translates to reloading a subset of the classes already loaded in a running virtual machine. It corresponds to the schema evolution 3 problem,which could be rather difficult to solve in general. Here are some of the difficulties:There may be live objects that are instances of a class we want to reload. These objects must be migrated to conform to the schema of the new class. For example, if the new version of the class contains a different set of instance fields, we must somehow map the existing set of instance field values to fields in the new version of the class.Similarly, we may have to map the static field values to a different set of static fields in the reloaded version of the class.The application may be executing a method that belongs to a class we want to reload.We do not address these problems in this paper. Instead, we show how it is sometimes possible to bypass them using class loaders. By organizing software components in separate class loaders, programmers can often avoid dealing with schema evolution. Instead, new classes are loaded by a separate loader.Figure 3 illustrates how a Server class can dynamically redirect the service requests to a new version of the Service class. The key technique is to load the server class, old service class, and new service class into separate class loaders. For example, we can define Server using the MyClassLoader class introduced in the last section.The Server.processRequest method redirects all incoming requests to a Service object stored in a p