01: package gnu.bytecode;
02:
03: /** Load classes from a set of byte arrays.
04: * @author Per Bothner
05: */
06:
07: public class ArrayClassLoader extends ClassLoader {
08: /** The raw byte arrays from which we will load the classes.
09: * Each element is suitable for defineClass. */
10: byte[][] classBytes;
11:
12: /** Number of classes managed by this loader. */
13: int size;
14:
15: /** Classes that we have already loaded. */
16: Class[] loadedClasses;
17:
18: String[] classNames;
19:
20: /** Load classes from the given byte arrays.
21: By convention, the classes we manage are named "lambda"+<INTEGER>. */
22: public ArrayClassLoader(byte[][] classBytes) {
23: this .classBytes = classBytes;
24: size = classBytes.length;
25: loadedClasses = new Class[size];
26: classNames = new String[size];
27: for (int i = 0; i < size; i++)
28: classNames[i] = "lambda" + i;
29: }
30:
31: public ArrayClassLoader(String[] classNames, byte[][] classBytes) {
32: this .classBytes = classBytes;
33: size = classBytes.length;
34: loadedClasses = new Class[size];
35: this .classNames = classNames;
36: }
37:
38: private void reserve(int count) {
39: if (count <= 0)
40: return;
41: int newLength = size < count ? size + count : 2 * size;
42: if (loadedClasses == null)
43: loadedClasses = new Class[newLength];
44: else if (size + count > loadedClasses.length) {
45: Class[] loadedClassesNew = new Class[newLength];
46: System.arraycopy(loadedClasses, 0, loadedClassesNew, 0,
47: size);
48: loadedClasses = loadedClassesNew;
49: }
50: if (classBytes == null)
51: classBytes = new byte[newLength][];
52: else if (size + count > classBytes.length) {
53: byte[][] classBytesNew = new byte[newLength][];
54: System.arraycopy(classBytes, 0, classBytesNew, 0, size);
55: classBytes = classBytesNew;
56: }
57: if (classNames == null)
58: classNames = new String[newLength];
59: else if (size + count > classNames.length) {
60: String[] classNamesNew = new String[newLength];
61: System.arraycopy(classNames, 0, classNamesNew, 0, size);
62: classNames = classNamesNew;
63: }
64: }
65:
66: public void addClass(String name, byte[] bytes) {
67: reserve(1);
68: classNames[size] = name == null ? ("lambda" + size) : name;
69: classBytes[size] = bytes;
70: size++;
71: }
72:
73: public Class loadClass(String name, boolean resolve)
74: throws ClassNotFoundException {
75: Class clas;
76: for (int index = 0;; index++) {
77: if (index >= size) {
78: clas = Class.forName(name);
79: break;
80: } else if (name.equals(classNames[index])) {
81: clas = loadedClasses[index];
82: if (clas == null) {
83: byte[] bytes = classBytes[index];
84: clas = defineClass(name, bytes, 0, bytes.length);
85: loadedClasses[index] = clas;
86: classBytes[index] = null; // To help garbage collector.
87: }
88: break;
89: }
90: }
91:
92: if (resolve)
93: resolveClass(clas);
94: return clas;
95: }
96: }
|