The first part. Tip
Do I need to read this article?
The Java class loader is critical to the operation of the Java system, but they are often ignored by us. Java class loader load
Find and load classes at runtime. Customized class loader can completely change the way the class is loaded, in the way you like.
Personalize your Java virtual machine. This article briefly introduces the Java class loader, then uses a constructed custom class loader.
Example to explain that this class loader automatically compiles the code before loading the class. What do you want to learn from the class loading?
How to create your own class loader. As long as you have some basic Java knowledge, you know how to create, compile, and transport
You can understand the content of this article in a command line Java program and some Java class files. Finish
This article, you should be able to:
* Expand the function of the Java virtual machine
* Create a custom class loader
* How to integrate custom class loaders into your application
* Modify your class loader to be compatible with Java2
Get help
There is any problem in this article, you can contact the author Greg Travis, the fuel tank: mito@panix.com.
Part II. Introduction
What is the class loader?
Different from Java and other languages, Java is running in Java Virtual Machine (JVM). This means that the compiled code is
One and platform-independent format is saved instead of running on a particular machine. This format and traditional
There are many important differences in executing code format. Specifically, different from C or C programs, Java programs are not a single
Established executable, but consisting of a lot of separate class files, each class file corresponds to a Java class. In addition, this
Some of the files are not loaded to memory immediately, but when the program needs it. The class loader is Java virtual
The machine is used to load the class into memory. Moreover, the Java class loader is also implemented with Java. This way you don't need it.
There is an in-depth understanding of Java virtual machines to easily create your own class loader.
Why create a class loader?
Since the Java virtual gold has already had a class loader, we have to create other things yourself? Default class loader
I only know how to load classes from the local system. When your program is compiled in this machine, the default class loader is generally worked.
It is very good. But one of the most exciting places in Java is very easy to load from the network without just local loading.
For example, the browser can load classes through a custom class loader. and also
Many ways to load classes. In addition to simple from the local or network, you can also be most exciting in custom Java.
One of the places:
* Automatically verify digital signatures before performing non-credit code
* Decrypt code according to the password provided by the user
* Create class according to user needs
Anything you care is convenient to integrate into your app in terms of bytecode.
Custom class loader example
If you have used AppletViewer in JDK (Java Software Development Pack) or other
Java embedded browser, you have used custom class loaders. When Sun has just released Java language, the most
A exciting thing is to watch Java how to perform code downloaded from the remote website. Execute from the remote site via HTT
P Connecting bytecode is a bit incredible. The reason why it works because Java has a custom class plus
The ability of the carrier. The small application browser contains a class loader that does not find a Java class locally, and
It is access to the remote server, load the original byte code file via HTTP, and then transform into the Java class in the Java virtual machine. when
However, the type of loader has made many things: they prevent unsafe Java classes, and keep different pages
The applet does not interfere with each other. A package echidna written by Luke Gorrie is an open Java package, he allows
A secure running multiple Java applications in a Java virtual machine. It gives each application by using a custom class loader
The copy of the sequence of a class file will prevent interference between the applications.
Our class loader example
We know how the class loader works, and we know how to define your own class loader. Next we create one
A custom class loader with a named Compiable ClassLoader (CCL). CCL is compiled for us, we will
Don't be compiled manually. This is basically equivalent to a "Make" program to build to our operating environment.
Note: We must figure out some related concepts before we carry out next step.
The system is in the JDK version 1.2 (that is, the Java 2 platform we said) has been improved. This article is in JDK1.0 and 1.1
The version is written, but all things work in later versions. ClassLoader is also improved in Java2.
The fifth part has a detailed introduction.
Part III.CLASSLOADER structure
Summary
The basic purpose of the type loader is to serve the request for the Java class. When a Java virtual machine requires a class, a class is
Name to the class loader, then the class loader attempts to return a corresponding class instance. Can be covered by different stages
The method to create a custom class loader. Next we will understand some of the main methods of the class loader. You will understand
What these methods are doing, how they work when loading a class file. You will also know to create a custom class plus
What code you need to write when the carrier. In the next section, you will use this knowledge and our custom CompilingCL
AssLoader works together.
Method LOADCLASS
ClassLoader.LoadClass () is the entry point of ClassLoader. The method is signed as follows:
Class loadClass (String name, Boolean Resolve);
Parameter Name Specifies the full name (including package name) required by the Java virtual machine, such as foo or java.lang.object.
Parameter resolve Specifies whether this class needs to be parsed
You can understand the parsing of the class as a completely prepared to run. Parrse is generally unnecessary. If Java virtual machine just want to know
Whether this class exists or wants to know its parent class, the resolution is completely unnecessary. In Java1.1 and it
Version, if you want to customize the class loader, the LoadClass method is the only way to cover over the subclass.
(ClassLoader has changed in Java1.2, providing method FindClass ()).
DEFINECLASS
DefineClass is a very mysterious way in ClassLoader. This method builds a class by one byte array.
example. This original byte array containing data may come from the file system, or it may be from the network. DefineClass table
The complexity, mystery and platform dependencies of the Java virtual machine - it converts it into runtime data by explaining the word code code
Structure, check validity, etc. But don't worry, these don't need you to do it. In fact, you can't overwrite it at all.
Because this method is modified by the keyword Final.
Method FINDSYSTEMCLASS
The FindSystemClass method loads files from the local system. It looks for class files in the local system, if found, call
DefineClass transforms the original byte array into classes. This is the default of the Java virtual machine loaded when running the Java application
mechanism. For custom class loaders, only FindsystemClass is required after we cannot load. Reason
Simple: Our class loader is responsible for performing certain steps in the load, but is not for all classes. such as,
Even if our class loader loads some classes from the remote site, there are still many basic classes to load from the local system.
These classes are not our concern, so we let Java virtual machines load them by default: from the local system. This
It is made by FindsystemClass. The entire process is approximately as follows: * Java virtual machine requests our custom class loader to load classes.
* We check if the remote site has this class that needs to be loaded.
* If there is, we get this class.
* If not, we think this is a class in the basic class library, calling FindsystemClass to load from the file system.
In most custom class loaders, you should call FindSystemClass first save time from remote lookup.
In fact, as we will see in the next part, only when we determine that we have automatically compiled our code.
Allow Java virtual machines to load classes from the local file system.
Method ResolVeclass
As mentioned above, class records can be divided into partially loaded (unresolved) and fully loaded (including parsing). We create self
When defining a class loader, you may have to call ResolVeclass.
FindlineedClass
FindloadedClass implements a cache: When you ask LoadClass to load a class, you can call this party first.
Method see if this class has been loaded and prevents re-loading a class that has been loaded. This method must be called first
Let's take a look at how these methods are organized together.
Our example implements the steps of loadClass to perform the following. (We don't specify a class file through some specific technology.
It is possible to compile from the network, from the compressed package or dynamic. In any case, we get the original byte code file)
* Call FindLoadedClass check if this class has been loaded.
* If we do not load, we get the original byte array in some way.
* If this array has been obtained, call DefineClass to transform it into a class object.
* If the original byte array cannot be obtained, call FindSystemClass to check if you can record from the local file system.
Load.
* If the parameter resolve is true, resolveclass is called to parse the class object.
* If you have not found a class yet, throw a classNotFoundException exception.
* Otherwise, return this class.
Now we have a comprehensive understanding of the application knowledge of class loaders, you can create a custom class loader. Next
Division, we will discuss CCL.
Part 4. Compiable ClassLoader
CCL show us the function of the class loader, and the purpose of the CCL is to allow our code to automatically compile and update. Below
How does it work?
* When there is a class request, first check if this class file is present on the current directory and subdirectories.
* If there is no class file, but there is a source code file, call the Java compiler to build a class file.
* If the class file already exists, check if the file is older than the source code file. If the class file is more than the source code file
Old, call the Java compiler to regenerate class files.
* If the compilation failed, or due to other reasons, it will not generate a class file from the source file, throw an exception classnotfou.
NDEXCEPTION.
* If this class has not yet been obtained, there may be other class libraries, call FindsystemClass to see if it can be found.
* If not found, throw an exception ClassNotFoundException.
* Otherwise, returns to this class.
How is Java compilation implementation?
Before we discuss, we need to figure out the Java compilation process. Usually, Java compiler is not only compiled
The classes of them are set. If the specified classes are required, it also compiles some other related classes. CCL will be one
Compiling those classes that we need to be compiled in your application. However, in general, the compiler is compiled after the first class,
CCL will find that other related classes of other needs have been compiled. why? The Java compiler uses our almost rules: if a class does not exist or the source file has been updated, it will compile this class. Java compiler basically
One step is earlier than CCL, most of the work is done by the Java compiler. We look like a CCL is compiling these classes.
In most cases, you will find it to call the compiler in the main function class, just these - simple one
It is enough to use it. However, there is a special case, these classes are not compiled when they appear. If you add according to the class name
To load a class, how to use Class.Forname, the Java compiler does not know if this class is needed. under these circumstances,
You find that the CCL calls the compiler again to compile the class. The code of the sixth part illustrates this process.
Use CompiLationClassLoader
In order to use CCL, we can't run our program directly, you must run in a special way, just like this:
% java foo arg1 arg2
We run it like this:
% Java cclrun foo arg1 arg2
CClrun is a special settle program that creates CompilingClassLoader and uses it to load our master.
Function class, this ensures that all the entire program is loaded by CompiLingClassLoader. CClrun uses JA
The VA reflects the API to call the main function of the main function class and deliver parameters to this function. Want to know more, refer to the sixth part
Source code.
Run example
We demonstrate how to work throughout the process.
The main program is a class named foo, which creates an instance of a class bar. This BAR instance creates an instance of class BAZ
The class baz exists in the package baz, which is to demonstrate how the CCL is loaded from the sub-package. Bar is also loaded based on class name BOO
This is also completed by CCL. All classes can be loaded. Use the source code from Chapter VI to execute this
program. Compile CCLRUN and COMPILINGCLASSLOADER. Make sure you don't compile other classes (Foo, Bar, Baz, A
ND boo), otherwise the CCL will not work.
% Java cclrun foo arg1 arg2
CCL: Compiable foo.java ...
Foo! arg1 arg2
Bar! arg1 arg2
Baz! arg1 arg2
CCL: Compiling Boo.java ...
Boo!
Note that the compiler is called for the first time for foo.java, and it is also compiled with Bar and Baz.baz together. Class Boo
When you need to load, the CCL once again calls the compiler to compile it.
The fifth part. Improvements to class loaders in Java2
Overview
In Java1.2 and later, the class loader has great improvements. The previous code can still work, but new
The system makes our implementation easier. This new model is the agent's entrustment model, that is, if this type of loader is not found.
To a class, it will make his parent class loader to find. The system class loader is a ancestor, system class loading of all class loaders.
Load classes by default - is also loaded from the local file system. Coverage LoadClass method generally try
Several ways to load the class, if you write a lot of class loaders, you will find that you are just once again in this complex party.
I have made some modifications in the law. Java1.2 LoadClass's default implementation contains the most common way to find classes, allowing
You override the FindClass method, and loadClass is appropriate whether the FindClass method is called. The advantage of this is that you are not
Need to override LoadClass, you only need to overwrite findclass, which can reduce workload.
New method: Findclass
This method is called by the default implementation of LoadClass. Findclass's goal is to include all class loader-specific code,
No need to repeat this code (such as calling the system class loader) when the specified method fails. New method: getSystemClassLoader
Regardless of whether you covers the method, Findclass and LoadClass, the method GetSystemClassLoader can directly access the department.
The category loader (instead of accessing indirect access by FindsystemClass).
New method: getParent
In order to delegate the request to the parent class loader, the parent class loader of this class loader can be obtained by this method. Be a custom
When the specific method in the righteous class loader cannot find a class, you may delegate the request to the parent class loader. Father of the type loader
The class loader contains code that creates this class loader.
Section 6. Source code
CompiLingClassLoader.java
The following is the contents of the file compiverclassloader.java
Import java.io. *;
/ *
CompilingClassLoader dynamically compiles the Java source file. It checks if the .class file exists, .class file is
No source file is old.
* /
Public Class CompilingClassLoader Extends ClassLoader
{
/ / Specify a file name, read the entire file content from the disk, return to the byte array.
Private Byte [] getBytes (String filename) throws oews oException {
// Get the file size.
File File = New File (filename);
Long len = file.length ();
// Creating an array just the content that can be stored.
BYTE RAW [] = new byte [(int) LEN];
// open a file
FileInputStream Fin = New FileInputStream (file);
// Read all content, if you can't read it, it indicates an error.
INT R = Fin.read (RAW);
IF (r! = len)
Throw new oException ("CAN't Read All," R "! =" LEN);
// Don't forget to turn the file.
Fin.close ();
// Return to this array.
Return RAW;
}
// Generate a process to compile the specified Java source file to develop file parameters. If the compile is successful, returns true, no,
// Return False.
Private Boolean Compile (String Javafile) throws oewception {
// Show current progress
System.out.println ("CCL: Compiable" JavaFile "...");
// Startup compiler
Process p = runtime.getime (). EXEC ("Javac" javafile;
// Waiting for compilation to end
Try {
p.WaitFor ();
} Catch (InterruptedException IE {System.out.Println (IE);}
// Check the return code to see if the compilation is wrong.
Int ret = p.exitvalue ();
// Returns to compile whether it is successful.
Return Ret == 0;
}
The core code of the // / loader - Loading the class automatically compiles the source file when needed.
Public Class LoadClass (String Name, Boolean Resolve)
Throws classnotfoundexception {
// Our goal is to get a class object.
Class clas = null; // First, check if this class is already happened.
Clas = findloadedclass (name);
//System.out.println ("FindloadedClass:" CLAS);
// Get the path name by class name, such as java.lang.object => java / lang / object
String filestub = name.replace ('.', '/');
// Build objects to source files and class files.
String javafilename = filestub "java";
String classfilename = filestub ". Class";
File javafile = new file (javaFilename);
File classfile = new file (classfilename);
//System.out.println ("j" javafail.lastmodified () "c"
// ClassFile.lastmodified ());
// First, it is judge whether it is necessary to compile. If the source file does not exist, or exist, but the source file
// Refer to the need to compile it.
IF (Javafile.exists () && (! ClassFile.exists () ||
JavaFile.lastmodified ()> classfile.lastmodified ())) {
Try {
// Compile, if the compilation failed, we must declare the cause of failure (not enough only using the old class).
IF (! COMPILE (JavaFileName) ||! ClassFile.exists ()) {
Throw new classnotfoundexception ("Compile Failed:" JavaFileName);
}
} catch (ioexception ie) {
// may compile IO errors.
Throw new classnotfoundexception (IE.toString ());
}
}
/ / Make sure we have compiled or need to be compiled, we start loading the original byte.
Try {
// Read byte.
Byte Raw [] = getBytes (ClassFileName);
// Translate into class object
Clas = defineClass (Name, Raw, 0, Raw.Length);
} catch (ioexception ie) {
// This does not mean failure, and the classes we have processed in the local class, such as java.lang.object.
}
//System.out.println ("DefineClass:" CLAS);
// May be loaded in the default manner in the class library.
IF (Clas == Null) {
Clas = FindsystemClass (Name);
}
//System.out.println ("FindsystemClass:" Clas);
// If the parameter resolve is true, the class is explained as needed.
IF (Resolve && Clas! = NULL)
ResolVeclass (Clas);
// If you haven't gotten yet, you have an error. IF (Clas == Null)
Throw New ClassNotFoundException (NAME);
/ / Otherwise, return this type of object.
Return Clas;
}
}
Ccrun.java
It is a ccrun.java file
Import java.lang.reflect. *;
/ *
CclRun runs the program with the Compiable ClassLoader.
* /
Public class cclrun
{
Static public void main (string args []) throws exception {
// The first parameter specifies the main function class to be run.
String progclass = args [0];
// The next parameter is the parameter passing to this main function class.
String progargs [] = new string [args.lendth-1];
System.Arraycopy (Args, 1, Progargs, 0, Progargs.Length);
// Create a CompiLingClassLoader
CompiableingClassLoader CCL = New CompilingClassLoader ();
// load the main function class through the CCL.
Class clas = ccl.loadClass (progclass);
// Use the reflection to call its main function and pass parameters.
// Generate a class object that represents the parameter type of the main function.
Class maingType [] = {(new string [0]). GetClass ()};
// Find the standard main function in the class.
Method main = Clas.getMethod ("main", maingtype;
// Create a list of parameters - here is a string array.
Object argsArray [] = {progargs};
// Call the main function.
Main.invoke (null, argsarray);
}
}
Foo.java
The following is the file foo.java content
Public Class Foo
{
Static public void main (string args []) throws exception {
System.out.println ("foo!" Args [0] " args [1]);
NEW BAR (Args [0], Args [1]);
}
}
Bar.java
The following is the file bar.java content
IMPORT Baz. *;
Public Class Bar
{
Public bar (string a, string b) {
System.out.println ("Bar!" A " B);
New baz (a, b);
Try {
Class Booclass = Class.Forname ("Boo");
Object boo = booclass.newinstance ();
} catch (exception e) {
E.PrintStackTrace ();
}
}
}
Baz / Baz.java
The following is file baz / baz.java content
Package baz;
Public Class Baz
{
Public Baz (String a, string b) {
System.out.println ("BAZ!" A " B);
}
}
Boo.java
The following is the fileboo.java content public class boo
{
Public boo () {
System.out.println ("BOO!");
}
}
Part 7. Summary
to sum up
By this article you realize that creating a custom class loader allows you to go deep into the Java virtual machine. You can
Any resource loaded file, or dynamically generate it so you can do much more you can do by extending these features.
Things, you can complete some powerful features.
Other topics about ClassLoader
Just as the beginning of this article, the custom class loader plays an important role in the Java embedded browser and the applet browser.
effect. The other features of the class loader are given below.
* Security: Customized class loader can check if it has the correct number before handing this class to the Java virtual machine
signature. You can also create a "sandbox" to prevent call to certain methods, which is to block the source code
This class is implemented in the operation other than the sandbox.
* Encryption: You can dynamically decode through the custom class loader, all your class files cannot be viewed by anti-compilation
Code. The user needs a password to run the program, which is used to decrypt the code.
* Archive: Do you need to release your code in some format or compression? Custom ClassLoader
Generate a band code file from any of the resources you want.
* Self-extract: You can compile the entire application into an executable class file, this file includes compression or
Data encrypted, there is an internal product loader, when the program is running, he is unproved to memory - no need
Before install.
* Dynamically generated: You can generate those categories that are referenced - the categories you need to use can be generated and then
Give the Java virtual machine.