Abstract:
A technique provides a hook that executes prior to a software application that is invisible to the software application. In an object-oriented execution environment, an imposter main class is loaded instead of the application main class. The imposter main class then manipulates the object-oriented execution environment to load the application main class without requiring knowledge of the application main class other than its name, and without requiring a change to the command line for the application.

Description:
BACKGROUND 
       [0001]    This disclosure relates generally to the field of computer software. More particularly, but not by way of limitation, it relates to a technique for injecting code into an application to be run prior to execution of the application. 
         [0002]    Software products that monitor software applications at runtime often need to execute code before the actual application starts to execute. The primary reason is enabling instrumentation of the application&#39;s code, but other pre-application processes may also be required. A technique that enables running code prior to software application code is often referred to as “hooking” or “placing a hook.” 
         [0003]    JAVA® software applications (JAVA is a registered trademark of Oracle America, Inc.) are required by the JAVA Virtual Machine (JVM) specifications to provide an entry point, which is a class that declares and implements the method “public static void main(String args[ ]).” This class is typically known as the “Main Class.” Its fully qualified name is provided to the JVM executable (e.g., java.exe) as a command line argument. Consequently, the JVM, which provides an object-oriented environment for JAVA programs, looks up a class file that contains the Main Class&#39;s bytecode, loads it and runs its “main( )” method, thus starting the application. Normally, the Main Class class-file will be located in the “application classpath”—a JVM variable that specifies locations on the disk where user-defined resources are located. 
         [0004]    One hooking technology that has been used is placing a new “Imposter Main Class” with the same fully qualified name as the actual application&#39;s Main class (referred here as the “Original Main Class”) in one of the directories specified for the classpath. As a result, imposter Main class will execute first, delegating execution to the original Main class only after running its own hook code. 
         [0005]    Class loading is the process of obtaining class bytes and transforming them into a “viable” entity in the JVM. This process is done by subclasses of java.lang.ClassLoader. According to what is known as the “class loading delegation model,” a ClassLoader in the JVM will first ask its parent ClassLoader (if such exists) to load the requested class before trying to load itself. This procedure is recursive, which means that a class will be loaded in the highest possible point in the ClassLoader hierarchy. 
         [0006]    “AppClassLoader” is the JVM ClassLoader “familiar” with the application classpath. Accordingly, it is the one requested to load the Main class. In compliance with the class loading delegation model, it delegates the request to its parent—“ExtClassLoader.” The latter is another JVM-internal ClassLoader of which classpath is composed of all Java ARchive (jar) files located in all directories specified by the JVM argument “java.ext.dirs.” Only after ExtClassLoader fails to load the Main class (since it is, normally, not part of its classpath) does the AppClassLoader loads the Main class itself. 
         [0007]    There are problems with the “naïve” Main class replacement described above. These problems include (a) problems with loading the original Main class, (b) problems with classes accessed by the original Main class, (c) problems accessing members (methods and fields) of the original Main class, and (d) problems with different Main classes in different processes. 
         [0008]    Due to the delegation model described above, the original Main class cannot be loaded in a conventional way (i.e., by invocation of any loadClass( )overload), because that will return the formerly loaded Imposter Main class. Instead, the original Main class&#39;s bytes are typically obtained and the class is explicitly defined via a defineClass( )method. Since the process of loading the first Main (i.e., the Imposter Main class) is initiated using AppClassLoader, AppClassLoader is recorded in the JVM as the initiating loader of the Main class, although the defining loader is actually ExtClassLoader. Trying to use AppClassLoader for defining the original Main class typically causes a problem in the JVM during the linkage process and a LinkageError is thrown as a result. That is why the Original Main is typically loaded using a new ClassLoader especially allocated for that purpose. That causes another problem, as the original ClassLoader hierarchy is completely altered. 
         [0009]    All classes and class-members with package-private access that are accessed by the Original Main class (e.g., the Original Main class&#39;s inner classes) must be loaded by the same ClassLoader that loaded the Original Main class. Otherwise, the two classes will not be seen in the same runtime package (which is defined by the package name and the defining loader) causing an IllegalAccessError. This means that all of those classes and class-members must be known in advance. 
         [0010]    All Original Main class members (methods and fields), even public ones, are not accessible to the rest of the application—any request for the Original Main class will yield the Imposter Main class (again, due to the delegation model). This can be worked around for methods by holding a reference to the Original Main class in the Imposter Main class, overloading required methods and delegating execution to the Original Main class. However, this means that the imposter Main class needs to be familiar with the Original Main class. There is no generic solution for the Original Main class&#39;s fields. 
         [0011]    In many cases, different Main classes can be used in different processes running different parts of the same application&#39;s code. If a process invoked by a Main class that is not overridden by an Imposter Main class uses a Main class that is overridden by an Imposter Main class, the process typically receives the Imposter Main class instead of the Original Main class. 
         [0012]    In addition to the class replacement technique described above, other techniques have been developed for injecting code into an application to run prior to the original Main class. 
         [0013]    In one conventional technique, the command line is changed to run a different Main class. The new Main class then executes hook code and then runs the “real” application&#39;s Main class. In this technique, instead of transferring the Main class name to the executable as a JVM parameter, it is transferred as a program parameter to the Main class that performs the hook. 
         [0014]    In another conventional technique, a JAVA Agent is employed to run code prior to any class loading. This JVM inherent hooking mechanism is not available in all versions of the JAVA development kit (JDK), and requires modifying the command line that runs the JAVA executable. 
         [0015]    Some JVMs expose a JVM Profiler Interface (JVMPI), intended for vendors to develop profilers that work in conjunction with that JVM. Using this application-programming interface (API) requires specifying the name of the profiler agent and the options to the profiler agent through a command line option to the JVM. Using this API opens a window in which to execute code, not necessarily written in the JAVA language, prior to application execution. 
         [0016]    These techniques require editing the command line for the application, which can be a very limiting restriction for products that are designed for use in unknown and extremely variable environments. For example, in order to place the hook, one needs to know where all scripts are that run the application and edit them correctly. The hook will not be active when running any script that was formed after the hook was installed. In production environments, changing the command line may require privileges that may be highly restricted and unavailable for normal users. In addition, modifying the command line may be impossible to perform when the JAVA environment is invoked by binary code such as an .exe file. Finally, a user may choose to run the application explicitly from the command line, avoiding the hook usage. 
         [0017]    Thus, a better technique for hooking application to provide code to run prior to execution of the Main class has been desired. 
       SUMMARY 
       [0018]    In one embodiment, a method is disclosed. The method comprises loading a first class in an object-oriented environment executing on a computer, manipulating the object-oriented environment by a method of the first class, and executing a method of the second class on the computer in the object-oriented environment. The act of manipulating the object-oriented environment by a method of the first class comprises loading a second class in the object-oriented environment and making the first class invisible to the second class. 
         [0019]    In another embodiment, a computer readable medium is disclosed. The computer readable medium has instructions for a programmable control device stored thereon wherein the instructions cause a programmable control device to perform the method described above. 
         [0020]    In yet another embodiment, a networked computer system is disclosed. The networked computer system comprises a first computer system and a second computer system, communicatively coupled to the first computer system. The first computer system comprises a first processor, a first software, which when executed causes the creation of an object-oriented environment on the first processor, and a second software, which when executed causes the object-oriented environment to load a first class into the object-oriented environment. The first class comprises logic to manipulate the object-oriented environment to load a second class of the object-oriented environment and logic to make the first class invisible to the second class. The second computer system comprises a second processor and a storage subsystem on which is stored the first class. 
     
    
     
       BRIEF DESCRIPTION OF THE DRAWINGS 
         [0021]      FIG. 1  illustrates, in graph form, an example of a ClassLoader hierarchy according to the prior art. 
           [0022]      FIG. 2  illustrates, in flowchart form, an embodiment of a technique for injecting hooking code into an application according to one embodiment. 
           [0023]      FIG. 3  illustrates, in graph form, an example collection of a ClassLoader tree after performance of the technique of  FIG. 2 . 
           [0024]      FIG. 4  illustrates, in block diagram form, an example computing device in which the techniques described above may execute according to one embodiment. 
           [0025]      FIG. 5  illustrates, in block diagram form, a network of computers and servers in which the techniques described above may execute and be stored according to one embodiment. 
       
    
    
     DETAILED DESCRIPTION 
       [0026]    In the following description, for purposes of explanation, numerous specific details are set forth in order to provide a thorough understanding of the invention. It will be apparent, however, to one skilled in the art that the invention may be practiced without these specific details. In other instances, structure and devices are shown in block diagram form in order to avoid obscuring the invention. References to numbers without subscripts or suffixes are understood to reference all instance of subscripts and suffixes corresponding to the referenced number. Moreover, the language used in this disclosure has been principally selected for readability and instructional purposes, and may not have been selected to delineate or circumscribe the inventive subject matter, resort to the claims being necessary to determine such inventive subject matter. Reference in the specification to “one embodiment” or to “an embodiment” means that a particular feature, structure, or characteristic described in connection with the embodiments is included in at least one embodiment of the invention, and multiple references to “one embodiment” or “an embodiment” should not be understood as necessarily all referring to the same embodiment. 
         [0027]    The following description is at times written using terminology and examples using JAVA®, J2EE®, or J2SE® components or environments. (JAVA, J2EE, and J2SE are registered trademarks of Oracle America, Inc.) Nevertheless, the present invention is not limited to such components or environments, and may be embodied in other programming languages, components, or environments as desired. 
         [0028]    Embodiments disclosed herein change the way Original Main class replacement is done, thus avoiding the problems described above, addresses the problem of placing hooks, and provides a significant improvement to the techniques known in the art for placing hooks. 
         [0029]    The use of these hooks is outside the scope of this invention and should be considered irrelevant for this invention. However, for illustrative purposes a few examples of how hooks can be used in general are provided below. 
         [0030]    Instrumentation purposes: This may be a rather complicated implementation, because a lot of the complexity is in the work that has to happen after hook was placed. However, using embodiments described herein for instrumentation purposes enables catching all application code. 
         [0031]    Change Runtime Behavior: A much simpler example would be one in which the user wants to perform a simple action, such as to print an image on the screen or send an email, before a given application starts running, without having to modify the application code. In this case, the hook code is executed once without influencing application execution. 
         [0032]    It should be clear to the reader that these examples are only provided to highlight the value of this invention. The list of examples is therefore not conclusive. 
         [0033]    The problems described above related to replacement of the Main class result from the alteration of the original ClassLoader hierarchy, and the duplicity of the Main class in that hierarchy, (i.e., having both the Original Main class and the Imposter Main class). Various embodiments solve these problems by creating a new, clean ClassLoader hierarchy after executing the desired hook code. In the new hierarchy, only one class file of the Main class exists, the original Main class. It is loaded in a conventional way by the ClassLoader that would have naturally loaded the original Main class. 
         [0034]      FIG. 1  is a graph illustrating the sun.misc.Launcher class  140  according the prior art. This is a JVM internal class, implemented very much like a singleton. It holds a single static instance reachable by a public static getter. Both the ExtClassLoader  120  and the AppClassLoader  130  are inner classes of the Launcher class  140 . When the JVM starts up, the single Launcher  140  instance is created. During this process, one ExtClassLoader  120  instance and one AppClassLoader  130  instance are created as well, each getting its classpath. The ExtClassLoader  120  has its parent set to be the native JVM root BootstrapClassLoader  110  and the AppClassLoader  130  has its parent set to be the ExtClassLoader  120  instance. When the application is loaded, a user ClassLoader  150  has its parent set to the AppClassLoader  130 , unless specified otherwise. 
         [0035]    The classpaths for the ExtClassLoader  120  and the AppClassLoader  130  are maintained separately by the JVM. Typically, the classpath for the ExtClassLoader  120  is identified by a JVM system property java.ext.dirs, while the AppClassLoader  130  classpath is identified by a JVM system property java.class.path. Thus, a class accessible by the ExtClassLoader  120  may be inaccessible to the AppClassLoader  130 . Multiple paths may be defined in the classpaths for the ExtClassLoader  120  and AppClassLoader  130 . The classpaths are typically identified to the JVM by the JAVA command line or by other techniques provided by an operating system of the computer running the JVM. The JVM obtains the classpath information and stores it in the JVM system properties as described above. 
         [0036]    In one embodiment, the imposter Main class may be stored in a directory tree location that is added to the ExtClassLoader  120  classpath (the ExtClassLoader  120  classpath is sometimes described as the extensions directories), but which is not added to the classpath of the AppClassLoader  130 , while the original Main class is stored in a directory tree location only in the classpath of the AppClassLoader  130 . Thus the original Main class may be inaccessible to the ExtClassLoader  120 . 
         [0037]      FIG. 2  is a flowchart illustrating a technique for hooking an application according to one embodiment. Before the JAVA process is started in the JVM, in block  210  the Imposter Main class file is placed in one of the libraries in the classpath of the Launcher  140 &#39;s ExtClassLoader  120 . The Imposter Main class has the same fully qualified name as the actual application&#39;s Main class. Then in block  220 , the JAVA process is started, creating the instance of the Launcher  140 , with its ExtClassLoader  120  and AppClassLoader  130 , setting their parents as illustrated in  FIG. 1 . 
         [0038]    The AppClassLoader  130  asks its parent ExtClassLoader  120  to load the Main class. Because the Imposter Main class is in the classpath of the ExtClassLoader  120 , the Imposter Main class is loaded instead of the original Main class, allowing the main( )method of the Imposter Main class to execute instead of the main( )method of the original Main class. 
         [0039]    In block  230 , the hook code of the Imposter Main class is executed using the main( )method of the Imposter Main class. This code may perform any desired actions, in addition to setting up the ClassLoader structures described below. In block  240 , the hook code creates a new instance of the sun.misc.Launcher class  140 . 
         [0040]    In block  250 , global references of the JVM are updated so that the JVM uses the ExtClassLoader  120  and the AppClassLoader of the new Launcher  140  when needing a ClassLoader. To avoid loading the Imposter Main class when attempting to load the original Main, the reference to the imposter Main class is removed from the classpath of the new ExtClassLoader  120  in block  260 . The original Main class may then be loaded through the new AppClassLoader  130  in block  270 , and the original Main class main method is invoked in block  280 . 
         [0041]    Thus, in one embodiment, the beginning of the hooking process is the same as in the simple Main class replacement described above: an Imposter Main is placed in a directory that is included in ExtClassLoader&#39;s classpath. Next, new ExtClassLoader  120  and AppClassLoader  130  instances are allocated, configured the same as the original instances. Then, using JAVA reflection technology, the Imposter Main class is excluded from the new ExtClassLoader&#39;s classpath. The final step of the process is loading the Original Main, using the new AppClassLoader  130  and invoking its main( ) method. 
         [0042]      FIG. 3  is a graph illustrating the relationships between Main classes and ClassLoader classes because of the technique illustrated in  FIG. 2 . Two Launcher instances  140  are created as described above. The existing ClassLoader hierarchy of ExtClassLoader  120  and AppClassLoader  130  is in the original Launcher  140 , indicated in  FIG. 3  with dashed lines. The new ClassLoader hierarchy of ExtClassLoader  120  and AppClassLoader  130  are in the new Launcher instance  140 . Both the original ClassLoader hierarchy and the new ClassLoader hierarchy are linked so that the parent of the ExtClassLoader  120  in each Launcher  140  is the BootStrapClassLoader  110 . Thus, the Imposter Main class  310  is loaded by the ExtClassLoader  120  of the original Launcher  140 , while the original Main class  320  is loaded by the AppClassLoader  130  of the new Launcher  140 . 
         [0043]    References to the original Launcher  140  and its corresponding AppClassLoader  130  are held in global locations of the JVM, available everywhere in the application and that were initialized during JVM startup, before the hook code started running. The hook code changes those references to be references to the new Launcher  140  and its corresponding AppClassLoader  130 , so that these will be the ones used when requested. In one embodiment, the references include a Launcher static field that references the Launcher instance  140  and the ClassLoader returned by the getter java.lang.ClassLoader.getSystemClassLoader( ). Using JAVA reflection technology, these references are reset to point at the new and valid instances. 
         [0044]    In one embodiment, the original ClassLoader tree trunk illustrated in  FIG. 3  is not used after the execution of the hook code, but remains alive in memory. However, the original Launcher instance  140  and its ExtClassLoader  120  and AppClassLoader  130  are all unreachable by the application code, thus making the hooking infrastructure of the imposter Main class  310  invisible to the application. 
         [0045]    The actual hook code must be executed prior to Original Main class launching. Besides being used for direct execution of any trivial actions, this code can manipulate application execution in indirect (yet unlimited) ways by modifying the state of the JVM or manipulating the new ClassLoader tree trunk. For example, in one embodiment, a monitoring program uses this hook, among other things, to place the infrastructure that allows instrumentation of the entire application code. 
         [0046]    Using the techniques described above avoids the need to edit the command line of the application and is not limited to specific JDKs. No trace of the hook code is visible to the application, and the hook code does not need to know anything about the Main class of the application other than its name. 
         [0047]    In one embodiment, the JVM may allow the creating of new ExtClassLoader  120  and AppClassLoader  130  instances without creating a new instance of the Launcher  140 . 
         [0048]    Referring now to  FIG. 4 , an example computer  FIG. 400  for use in providing a hooking code is illustrated in block diagram form. Example computer  FIG. 400  comprises a system unit  FIG. 410  which may be optionally connected to an input device or system  FIG. 460  (e.g., keyboard, mouse, touch screen, etc.) and display  FIG. 470 . A program storage device (PSD)  FIG. 480  (sometimes referred to as a hard disc) is included with the system unit  FIG. 410 . Also included with system unit  FIG. 410  is a network interface  FIG. 440  for communication via a network with other computing and corporate infrastructure devices (not shown). Network interface  FIG. 440  may be included within system unit  FIG. 410  or be external to system unit  FIG. 410 . In either case, system unit  FIG. 410  will be communicatively coupled to network interface  FIG. 440 . Program storage device  FIG. 480  represents any form of non-volatile storage including, but not limited to, all forms of optical and magnetic, including solid-state, storage elements, including removable media, and may be included within system unit  FIG. 410  or be external to system unit  FIG. 410 . Program storage device  FIG. 480  may be used for storage of software to control system unit  FIG. 410 , data for use by the computer  FIG. 400 , or both. 
         [0049]    System unit  FIG. 410  may be programmed to perform methods in accordance with this disclosure (an example of which is in  FIG. 2 ). System unit  FIG. 410  comprises a processor unit (PU)  FIG. 420 , input-output (I/O) interface  FIG. 450  and memory  FIG. 430 . Processing unit  FIG. 420  may include any programmable controller device including, for example, one or more members of the Intel Atom®, Core®, Pentium® and Celeron® processor families from Intel Corporation and the Cortex and ARM processor families from ARM. (INTEL, INTEL ATOM, CORE, PENTIUM, and CELERON are registered trademarks of the Intel Corporation. CORTEX is a registered trademark of the ARM Limited Corporation. ARM is a registered trademark of the ARM Limited Company.) Memory  FIG. 430  may include one or more memory modules and comprise random access memory (RAM), read only memory (ROM), programmable read only memory (PROM), programmable read-write memory, and solid-state memory. One of ordinary skill in the art will also recognize that PU  FIG. 420  may also include some internal memory including, for example, cache memory. 
         [0050]    In one embodiment, illustrated in  FIG. 5 , the application may run in a JVM on one computer  510 . The application may be loaded from the computer  510  or may be loaded from a storage system  540  controlled by a file server  530 . Similarly, the hooking code performing the techniques described above may be loaded from the computer  510  or may be loaded from a storage system  540  controlled by the file server  530 . The computer  510  may be connected to the file server  530  by one or more networks  520 . 
         [0051]    It is to be understood that the above description is intended to be illustrative, and not restrictive. For example, the above-described embodiments may be used in combination with each other. Many other embodiments will be apparent to those of skill in the art upon reviewing the above description. The scope of the invention therefore should be determined with reference to the appended claims, along with the full scope of equivalents to which such claims are entitled. In the appended claims, the terms “including” and “in which” are used as the plain-English equivalents of the respective terms “comprising” and “wherein.”