Step 1: Create an object for the compiled class file and its package name.
1) source code of the class file
Java code
- Package com. WSC. classloader;
- Public class tool {
- Public void print (){
- }
- }
2) use javac tool. Java to compile a class file
3) read the tool. Class file to the memory and generate a byte [] Array
Java code
- /**
- * Load the class file
- *
- * @ Param clazzpath
- * Class absolute file path
- * @ Return byte array
- * @ Throws ioexception
- */
- Private byte [] loadclassfile (string clazzpath) throws ioexception {
- Fileinputstream FCM = new fileinputstream (clazzpath );
- Bufferedinputstream Bis = new bufferedinputstream (FCM );
- Bytearrayoutputstream baos = new bytearrayoutputstream ();
- Byte [] buffer = new byte [1024*256];
- Int CH = 0;
- While (CH = bis. Read (buffer, 0, buffer. Length ))! =-1 ){
- Baos. Write (buffer, 0, CH );
- }
- Return baos. tobytearray ();
- }
4) customize classloader and use the defineclass method in classloader: protected final class <?> Defineclass (string name, byte [] B, int off, int Len ). The parameters are the class names, the byte array corresponding to the class file, the start position and the end position.
Java code
- @ Override
- Protected class <?> Loadclass (string name, Boolean resolve)
- Throws classnotfoundexception {
- Class <?> C = findloadedclass (name );
- If (C = NULL ){
- C = defineclass (name, Data, 0, Data. Length );
- }
- Return C;
- }
The overall code is:
Java code
- Package com. WSC. classloader;
- Import java. Io. bufferedinputstream;
- Import java. Io. bytearrayoutputstream;
- Import java. Io. fileinputstream;
- Import java. Io. ioexception;
- Public class classloaderone extends classloader {
- Public static void main (string [] ARGs) throws exception {
- Classloaderone loader = new classloaderone (
- "E: \ Java \ javafx \ classloader \ libs \ tool. Class ");
- Class <?> Clazz = loader. loadclass ("com. WSC. classloader. tool ");
- Object o = clazz. newinstance ();
- System. Out. println (O. getclass (). getclassloader ());
- }
- Private byte [] data;
- Public classloaderone (string clazzpath) throws ioexception {
- Data = loadclassfile (clazzpath );
- }
- /**
- * Load the class file
- *
- * @ Param clazzpath
- * Class absolute file path
- * @ Return byte array
- * @ Throws ioexception
- */
- Private byte [] loadclassfile (string clazzpath) throws ioexception {
- Fileinputstream FCM = new fileinputstream (clazzpath );
- Bufferedinputstream Bis = new bufferedinputstream (FCM );
- Bytearrayoutputstream baos = new bytearrayoutputstream ();
- Byte [] buffer = new byte [1024*256];
- Int CH = 0;
- While (CH = bis. Read (buffer, 0, buffer. Length ))! =-1 ){
- Baos. Write (buffer, 0, CH );
- }
- Return baos. tobytearray ();
- }
- @ Override
- Protected class <?> Loadclass (string name, Boolean resolve)
- Throws classnotfoundexception {
- Class <?> C = findloadedclass (name );
- If (C = NULL ){
- C = defineclass (name, Data, 0, Data. Length );
- }
- Return C;
- }
- }
It feels like this. Run the following command:
Java code
- Exception in thread "Main" Java. Lang. securityexception: prohibited package name: Java. Lang
- At java. Lang. classloader. predefineclass (unknown source)
- At java. Lang. classloader. defineclass (unknown source)
- At java. Lang. classloader. defineclass (unknown source)
- At com. WSC. classloader. classloaderone. loadclass (classloaderone. Java: 52)
- At java. Lang. classloader. loadclass (unknown source)
- At java. Lang. classloader. defineclass1 (native method)
- At java. Lang. classloader. defineclass (unknown source)
- At java. Lang. classloader. defineclass (unknown source)
- At com. WSC. classloader. classloaderone. loadclass (classloaderone. Java: 52)
- At java. Lang. classloader. loadclass (unknown source)
- At com. WSC. classloader. classloaderone. Main (classloaderone. Java: 14)
It means that the package named java. Lang cannot be loaded.
The reason is: although the tool class does not use any introduced Java. lang class, but its parent class object is in Java. in Lang, when the classloader loads the tool class, it loads all its relational networks. The parent class object must be loaded.
This is simple! You only need to write one more if else. Use the parent loader (each class loader has a parent class loader) to load.
Java code
- @ Override
- Protected class <?> Loadclass (string name, Boolean resolve)
- Throws classnotfoundexception {
- Class <?> C = findloadedclass (name );
- If (name. Equals ("Java. Lang. Object ")){
- Classloader parent = getparent ();
- C = parent. loadclass (name );
- }
- If (C = NULL ){
- C = defineclass (name, Data, 0, Data. Length );
- }
- Return C;
- }
The result is:
Java code
- Com. WSC. classloader. classloaderone @ ca470
Step 2: New Problems
Java code
- Method [] Methods = clazz. getmethods ();
- For (INT I = 0; I <methods. length; I ++ ){
- String name = methods [I]. getname ();
- System. Out. println (name );
- Class <?> [] Params = methods [I]. getparametertypes ();
- For (Int J = 0; j <Params. length; j ++ ){
- System. Out. println (Params [J]. tostring ());
- }
- }
At this time, the error will still be reported, because the method class is also under the java. lang Package, only one if else can be added.
Obviously, the code should be written like this
Java code
- @ Override
- Protected class <?> Loadclass (string name, Boolean resolve)
- Throws classnotfoundexception {
- Class <?> C = findloadedclass (name );
- If (C = NULL ){
- // If the parent loader is not null, use the parent loader to load (such as core classes such as object and hashmap)
- If (getparent ()! = NULL ){
- Try {
- C = getparent (). loadclass (name );
- } Catch (exception e ){
- // If the parent class is not loaded, an exception is thrown.
- }
- }
- // If the parent class loader is not loaded, use the custom loader to load it.
- If (C = NULL ){
- C = defineclass (name, Data, 0, Data. Length );
- }
- }
- Return C;
- }
Print result:
Java code
- Tostring
- Print
- Class java. Lang. String
- Getclass
- Hashcode
- Equals
- Class java. Lang. Object
- Notify
- Policyall
- Wait
- Long
- Int
- Wait
- Wait
- Long
- Com. WSC. classloader. classloaderone @ fcfa52
Step 3: If you can create a local file using the. Class file, the same principle applies to the remote file. (If you need to encrypt the file, you can decrypt it locally ). If the class file is called remotely, the local interface or reflection method is generally used. The first choice is the interface. The first choice is the efficiency, but it is too troublesome to know the names and parameters of all methods.
The remote loading of class files to the local machine makes it difficult to locate the error location if an error occurs. Fortunately, the use of classloader rules is used based on urlclassloader by default. The system first checks whether the class exists locally. Therefore, you can directly place the source code to debug it. Of course, you must delete it when releasing it.
You can use this basic getting started program to understand the basic process of classloader.