FileDocCategorySizeDatePackage
ClassLoader.javaAPI DocJava SE 6 API8324Tue Jun 10 00:22:24 BST 2008com.sun.org.apache.bcel.internal.util

ClassLoader

public class ClassLoader extends ClassLoader

Drop in replacement for the standard class loader of the JVM. You can use it in conjunction with the JavaWrapper to dynamically modify/create classes as they're requested.

This class loader recognizes special requests in a distinct format, i.e., when the name of the requested class contains with "$$BCEL$$" it calls the createClass() method with that name (everything bevor the $$BCEL$$ is considered to be the package name. You can subclass the class loader and override that method. "Normal" classes class can be modified by overriding the modifyClass() method which is called just before defineClass().

There may be a number of packages where you have to use the default class loader (which may also be faster). You can define the set of packages where to use the system class loader in the constructor. The default value contains "java.", "sun.", "javax."

version
$Id: ClassLoader.java,v 1.1.2.1 2005/07/31 23:47:03 jeffsuttor Exp $
author
M. Dahm
see
JavaWrapper
see
ClassPath

Fields Summary
private Hashtable
classes
private String[]
ignored_packages
private Repository
repository
private ClassLoader
deferTo
Constructors Summary
public ClassLoader()


    
  
public ClassLoader(ClassLoader deferTo)

    this.deferTo = deferTo;
    this.repository = new ClassLoaderRepository(deferTo);
  
public ClassLoader(String[] ignored_packages)

param
ignored_packages classes contained in these packages will be loaded with the system class loader

    addIgnoredPkgs(ignored_packages);
  
public ClassLoader(ClassLoader deferTo, String[] ignored_packages)

    this.deferTo = deferTo;
    this.repository = new ClassLoaderRepository(deferTo);

    addIgnoredPkgs(ignored_packages);
  
Methods Summary
private voidaddIgnoredPkgs(java.lang.String[] ignored_packages)

    String[] new_p = new String[ignored_packages.length + this.ignored_packages.length];
	
    System.arraycopy(this.ignored_packages, 0, new_p, 0, this.ignored_packages.length);
    System.arraycopy(ignored_packages, 0, new_p, this.ignored_packages.length,
		     ignored_packages.length);

    this.ignored_packages = new_p;
  
protected com.sun.org.apache.bcel.internal.classfile.JavaClasscreateClass(java.lang.String class_name)
Override this method to create you own classes on the fly. The name contains the special token $$BCEL$$. Everything before that token is consddered to be a package name. You can encode you own arguments into the subsequent string. You must regard however not to use any "illegal" characters, i.e., characters that may not appear in a Java class name too
The default implementation interprets the string as a encoded compressed Java class, unpacks and decodes it with the Utility.decode() method, and parses the resulting byte array and returns the resulting JavaClass object.

param
class_name compressed byte code with "$$BCEL$$" in it

    int    index     = class_name.indexOf("$$BCEL$$");
    String real_name = class_name.substring(index + 8);

    JavaClass clazz = null;
    try {
      byte[]      bytes  = Utility.decode(real_name, true);
      ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo");

      clazz = parser.parse();
    } catch(Throwable e) {
      e.printStackTrace();
      return null;
    }

    // Adapt the class name to the passed value
    ConstantPool cp = clazz.getConstantPool();

    ConstantClass cl = (ConstantClass)cp.getConstant(clazz.getClassNameIndex(),
						     Constants.CONSTANT_Class);
    ConstantUtf8 name = (ConstantUtf8)cp.getConstant(cl.getNameIndex(),
						     Constants.CONSTANT_Utf8);
    name.setBytes(class_name.replace('.", '/"));

    return clazz;
  
protected java.lang.ClassloadClass(java.lang.String class_name, boolean resolve)

    Class cl = null;

    /* First try: lookup hash table.
     */
    if((cl=(Class)classes.get(class_name)) == null) {
      /* Second try: Load system class using system class loader. You better
       * don't mess around with them.
       */
      for(int i=0; i < ignored_packages.length; i++) {
	if(class_name.startsWith(ignored_packages[i])) {
	  cl = deferTo.loadClass(class_name);
	  break;
	}
      }

      if(cl == null) {
	JavaClass clazz = null;

	/* Third try: Special request?
	 */
	if(class_name.indexOf("$$BCEL$$") >= 0)
	  clazz = createClass(class_name);
	else { // Fourth try: Load classes via repository
	  if ((clazz = repository.loadClass(class_name)) != null) {
	    clazz = modifyClass(clazz);
	  }
	  else
	    throw new ClassNotFoundException(class_name);
	}

	if(clazz != null) {
	  byte[] bytes  = clazz.getBytes();
	  cl = defineClass(class_name, bytes, 0, bytes.length);
	} else // Fourth try: Use default class loader
	  cl = Class.forName(class_name);
      }
      
      if(resolve)
	resolveClass(cl);
    }

    classes.put(class_name, cl);

    return cl;
  
protected com.sun.org.apache.bcel.internal.classfile.JavaClassmodifyClass(com.sun.org.apache.bcel.internal.classfile.JavaClass clazz)
Override this method if you want to alter a class before it gets actually loaded. Does nothing by default.

    return clazz;