Implementation of a simple custom ClassLoader

Source: Internet
Author: User

 


In many cases, some custom ClassLoader is used instead of the system Class Loader. Most of the time, people do this because they cannot predict which classes are needed during the runtime during compilation. Especially in those appservers, such as tomcat, aveon-phonix, and Jboss. Or the program provides some plug-in functions. You can add your own functions after the program is compiled, such as ant and jxta-shell. It is easy to customize a ClassLoader. Generally, you only need to understand a few methods.
A simple custom ClassLoader inherits from the ClassLoader class. Here we need to create a ClassLoader that can specify a path at runtime to load the class under this path.
Generally, we use the ClassLoader. loadClass (String): Class method. By providing a Class name, we will get a corresponding Class instance. Therefore, as long as we make a small change to this method, we can achieve our aspirations.
Source code:

Protected synchronized Class loadClass (String name, boolean resolve) throws ClassNotFoundException {/First, check if the class has already been loaded Class c = findLoadedClass (name ); if (c = null) {try {if (parent! = Null) {c = parent. loadClass (name, false);} else {c = findBootstrapClass0 (name);} catch (ClassNotFoundException e) {// If still not found, then call findClass in order // to find the class. c = findClass (name) ;}}if (resolve) {resolveClass (c) ;}return c ;}

Source from ClassLoader. java

First, check JavaAPI doc: the steps of the default loadClass method are shown above.
1. call findLoadedClass (String): The Class checks whether the class has been loaded. The JVM specification specifies that ClassLoader can cache the Class it loads, therefore, if a class has been loaded, you can directly obtain it from the cache.
2. Call its parent loadClass () method. If the parent is empty, use the class loader (the famous bootstrap classloader) in the JVM ).
3. If neither of the above two steps is found, call the findClass (String) method to find and load the class.
There is another saying that after Java 1.2, we encourage users to inherit the findClass (String) method to implement their own class loader instead of inheriting the loadClass (String) method.
In this case, we will do this first :)

Public class AnotherClassLoader extends ClassLoader {private String baseDir; private static final Logger LOG = Logger. getLogger (AnotherClassLoader. class); public AnotherClassLoader (ClassLoader parent, String baseDir) {super (parent); this. baseDir = baseDir;} protected Class findClass (String name) throws ClassNotFoundException {LOG. debug ("findClass" + name); byte [] bytes = loadClassBytes (name); Class theClass = defineClass (name, bytes, 0, bytes. length); // A if (theClass = null) throw new ClassFormatError (); return theClass;} private byte [] loadClassBytes (String className) throws ClassNotFoundException {try {String classFile = getClassFile (className); FileInputStream FD = new FileInputStream (classFile); FileChannel fileC = fiis. getChannel (); ByteArrayOutputStream baos = new ByteArrayOutputStream (); WritableByteChannel outC = Channels. newChannel (baos); ByteBuffer buffer = ByteBuffer. allocateDirect (1024); while (true) {int I = fileC. read (buffer); if (I = 0 | I =-1) {break;} buffer. flip (); outC. write (buffer); buffer. clear ();} FCM. close (); return baos. toByteArray ();} catch (IOException fnfe) {throw new ClassNotFoundException (className);} private String getClassFile (String name) {StringBuffer sb = new StringBuffer (baseDir ); name = name. replace (., file. separatorChar) + ". class "; sb. append (File. separator + name); return sb. toString ();}}

[I] Ps: some code of nio of JDK1.4 is used here: [/I]
Very simple code. The key is in A. We use the defineClass method to convert the binary array obtained from the class file to the corresponding Class instance. DefineClass is a native method. It identifies the class file format for us, analyzes and reads the corresponding data structure, and generates a class instance.

Before we finish, we just found the class released in a directory, and there are resources. Sometimes we use Class. getResource (): URL to obtain the corresponding resource file. If the above ClassLoader is used only, the corresponding return value is null.

Let's take a look at the internal structure of the original ClassLoader.

Public java.net. URL getResource (String name) {name = resolveName (name); ClassLoader cl = getClassLoader0 (); // here if (cl = null) {// A system class. return ClassLoader. getSystemResource (name);} return cl. getResource (name );}


It turns out that the classLoader that loads this class gets the resource.


Public URL getResource (String name) {URL url; if (parent! = Null) {url = parent. getResource (name) ;}else {url = getBootstrapResource (name) ;}if (url = null) {url = findResource (name); // here} return url ;}




In this case, you only need to inherit the findResource (String) method. Modify the following code:


// A newly added findResource method protected URL findResource (String name) {LOG. debug ("findResource" + name); try {URL url = super. findResource (name); if (url! = Null) return url; url = new URL ("file: //" + converName (name); // simplify processing, all resources get return url from the file system;} catch (MalformedURLException mue) {LOG. error ("findResource", mue); return null ;}} private String converName (String name) {StringBuffer sb = new StringBuffer (baseDir); name = name. replace (., file. separatorChar); sb. append (File. separator + name); return sb. toString ();}


Now, a simple custom ClassLoader is ready. You can add other spices (such as security check and class file modification) to suit your taste :)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.