ClassLoaderpublic 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." |
Fields Summary |
---|
private Hashtable | classes | private String[] | ignored_packages |
Constructors Summary |
---|
public ClassLoader()
| public ClassLoader(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;
|
Methods Summary |
---|
protected com.sun.org.apache.bcel.internal.classfile.JavaClass | createClass(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 thee resulting byte array and returns the resulting JavaClass object.
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.Class | loadClass(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 = Class.forName(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
clazz = modifyClass(Repository.lookupClass(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.JavaClass | modifyClass(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;
|
|