Changeset 14015


Ignore:
Timestamp:
07/23/12 11:58:34 (8 years ago)
Author:
Mark Evenson
Message:

dmiles: classloaders to search their parent/system classloaders first.

Robustifies strategies for loading in non-JVM environments (iKVM/GCJ)
when using the "class" PATHNAME TYPE for bytecode artifacts.

Location:
trunk/abcl/src/org/armedbear/lisp
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/FaslClassLoader.java

    r14002 r14015  
    6060         */
    6161        if (name.startsWith(baseName + "_")) {
    62             String internalName = "org/armedbear/lisp/" + name;
     62            String internalName = name.replace(".", "/");
     63            if (!internalName.contains("/")) internalName = "org/armedbear/lisp/" + internalName;
    6364            Class<?> c = this.findLoadedClass(internalName);
    6465
     66            if (c == null && checkPreCompiledClassLoader) {
     67              c = findPrecompiledClassOrNull(name);
     68              // Oh, we have to return here so we don't become the owning class loader?
     69              if (c != null)
     70                  return c;
     71            }           
    6572            if (c == null) {
    6673                c = findClass(name);
     
    8188    protected Class<?> findClass(String name) throws ClassNotFoundException {
    8289        try {
     90            if (checkPreCompiledClassLoader) {
     91              Class<?> c = findPrecompiledClassOrNull(name);
     92              if (c != null)
     93                return c;                 
     94            }
    8395            byte[] b = getFunctionClassBytes(name);
    84             return defineClass(name, b, 0, b.length);
     96            return defineLispClass(name, b, 0, b.length);
    8597        } catch(Throwable e) { //TODO handle this better, readFunctionBytes uses Debug.assert() but should return null
    8698            e.printStackTrace();
     
    111123    }
    112124
    113     public byte[] getFunctionClassBytes(String name) {
    114         Pathname pathname = new Pathname(name.substring("org/armedbear/lisp/".length()) + "." + Lisp._COMPILE_FILE_CLASS_EXTENSION_.symbolValue().getStringValue());
    115         return readFunctionBytes(pathname);
    116     }
    117 
    118     public byte[] getFunctionClassBytes(Class<?> functionClass) {
    119         return getFunctionClassBytes(functionClass.getName());
    120     }
    121 
    122     public byte[] getFunctionClassBytes(Function f) {
    123         byte[] b = getFunctionClassBytes(f.getClass());
    124         f.setClassBytes(b);
    125         return b;
    126     }
    127 
    128125    public LispObject loadFunction(int fnNumber) {
    129126        //Function name is fnIndex + 1
    130127        String name = baseName + "_" + (fnNumber + 1);
    131128        try {
    132             Function f = (Function) loadClass(name).newInstance();
    133             f.setClassBytes(getFunctionClassBytes(name));
     129            Class clz = loadClass(name);
     130            Function f = (Function) clz.newInstance();
     131            if (clz.getClassLoader() instanceof JavaClassLoader) {
     132                // Don't do this for system classes (though probably dont need this for other classes)
     133                f.setClassBytes(getFunctionClassBytes(name));
     134            }
    134135            return f;
    135136        } catch(Throwable e) {
  • trunk/abcl/src/org/armedbear/lisp/JavaClassLoader.java

    r13369 r14015  
    3939import java.util.HashSet;
    4040import java.util.Set;
     41import java.io.DataInputStream;
     42import java.io.IOException;
     43import java.io.InputStream;
    4144import java.net.URL;
    4245import java.net.URLClassLoader;
     
    4649    private static JavaClassLoader persistentInstance;
    4750
     51    public static boolean checkPreCompiledClassLoader = true;
     52   
     53    public Class<?> loadClass(String name) throws ClassNotFoundException {
     54        if (checkPreCompiledClassLoader) {
     55            Class<?> c = findPrecompiledClassOrNull(name);
     56            if (c != null) {
     57                return c;                       
     58            }
     59        }
     60        return loadClass(name, false);
     61    }
     62   
     63    /**
     64     * Returns a class loaded by the system or bootstrap class loader;
     65     * or return null if not found.
     66     *
     67     * On AOT systems like GCJ and IKVM this means a class implemented in ASM or CLR
     68     *
     69     * like findLoadedClass it does not throw an exception if a class is not found
     70     */
     71    public Class<?> findPrecompiledClassOrNull(String name) {
     72        ClassLoader ourCL = JavaClassLoader.class.getClassLoader();
     73        while (ourCL != null) {
     74            try {
     75                return Class.forName(name, true, ourCL);
     76            } catch (ClassNotFoundException cnf) {
     77            }
     78            ourCL = ourCL.getParent();
     79        }
     80        try {
     81            return findSystemClass(name);
     82        } catch (ClassNotFoundException e) {
     83            return null;
     84        }
     85    }
     86   
     87    public byte[] getFunctionClassBytes(String name) {
     88        Pathname pathname
     89            = new Pathname(name.substring("org/armedbear/lisp/".length())
     90                           + "." + Lisp._COMPILE_FILE_CLASS_EXTENSION_.symbolValue().getStringValue());
     91        return readFunctionBytes(pathname);
     92    }
     93
     94    public byte[] getFunctionClassBytes(Class<?> functionClass) {
     95        String className = functionClass.getName();
     96        try {
     97            String ext = Lisp._COMPILE_FILE_CLASS_EXTENSION_.symbolValue().getStringValue();
     98            InputStream is = getResourceAsStream(className.replace('.', '/') + "." + ext);
     99            if (is != null) {
     100                byte[] imgDataBa = new byte[(int) is.available()];
     101                DataInputStream dataIs = new DataInputStream(is);
     102                dataIs.readFully(imgDataBa);
     103                return imgDataBa;
     104            }
     105        } catch (IOException e) {
     106        }
     107        return getFunctionClassBytes(className);
     108    }
     109
     110    final public byte[] getFunctionClassBytes(Function f) {
     111        byte[] b = getFunctionClassBytes(f.getClass());
     112        f.setClassBytes(b);
     113        return b;
     114    }
     115
    48116    private static Set<String> packages = Collections.synchronizedSet(new HashSet<String>());
    49117
     
    54122
    55123    public JavaClassLoader(ClassLoader parent) {
    56   super(new URL[] {}, parent);
     124        super(new URL[] {}, parent);
    57125    }
    58126
    59127    public JavaClassLoader(URL[] classpath, ClassLoader parent) {
    60   super(classpath, parent);
     128        super(classpath, parent);
    61129    }
    62130
     
    70138        if (persistentInstance == null)
    71139            persistentInstance = new JavaClassLoader();
    72   definePackage(packageName);
     140        definePackage(packageName);
    73141        return persistentInstance;
    74142    }
     
    90158    {
    91159        try {
    92             long length = classbytes.length;
     160            long length = classbytes.length; 
    93161            if (length < Integer.MAX_VALUE) {
    94162                Class<?> c =
    95                     defineClass(className, classbytes, 0, (int) length);
     163                    defineLispClass(className, classbytes, 0, (int) length);
    96164                if (c != null) {
    97165                    resolveClass(c);
     
    100168            }
    101169        }
    102       catch (LinkageError e) {
     170        catch (LinkageError e) {
    103171                throw e;
    104       }
     172        }
    105173        catch (Throwable t) {
    106174            Debug.trace(t);
     
    109177    }
    110178
     179    protected final Class<?> defineLispClass(String name, byte[] b, int off, int len)
     180                throws ClassFormatError {       
     181        ///if (checkPreCompiledClassLoader) Debug.trace("DEFINE JAVA CLASS " + name + " " + len);
     182        return defineClass(name, b, off, len);
     183    }
     184   
    111185    public Class<?> loadClassFromByteArray(String className, byte[] bytes,
    112186                                                int offset, int length)
    113187    {
    114188        try {
    115             Class<?> c = defineClass(className, bytes, offset, length);
     189            Class<?> c = defineLispClass(className, bytes, offset, length);
    116190            if (c != null) {
    117191                resolveClass(c);
     
    131205    @Override
    132206    public void addURL(URL url) {
    133   super.addURL(url);
     207        super.addURL(url);
    134208    }
    135209
     
    138212    private static final Primitive GET_DEFAULT_CLASSLOADER = new pf_get_default_classloader();
    139213    private static final class pf_get_default_classloader extends Primitive {
    140  
    141   private final LispObject defaultClassLoader = new JavaObject(new JavaClassLoader());
     214       
     215        private final LispObject defaultClassLoader = new JavaObject(new JavaClassLoader());
    142216
    143217        pf_get_default_classloader() {
     
    147221        @Override
    148222        public LispObject execute() {
    149       return defaultClassLoader;
     223            return defaultClassLoader;
    150224        }
    151225    };
     
    162236        @Override
    163237        public LispObject execute() {
    164       return new JavaObject(new JavaClassLoader(getCurrentClassLoader()));
     238            return new JavaObject(new JavaClassLoader(getCurrentClassLoader()));
    165239        }
    166240
    167241        @Override
    168242        public LispObject execute(LispObject parent) {
    169       return new JavaObject(new JavaClassLoader((ClassLoader) parent.javaInstance(ClassLoader.class)));
     243            return new JavaObject(new JavaClassLoader((ClassLoader) parent.javaInstance(ClassLoader.class)));
    170244        }
    171245    };
     
    182256        @Override
    183257        public LispObject execute() {
    184       return execute(new JavaObject(getCurrentClassLoader()));
     258            return execute(new JavaObject(getCurrentClassLoader()));
    185259        }
    186260
    187261        @Override
    188262        public LispObject execute(LispObject classloader) {
    189       LispObject list = NIL;
    190       Object o = classloader.javaInstance();
    191       while(o instanceof ClassLoader) {
    192     ClassLoader cl = (ClassLoader) o;
    193     list = list.push(dumpClassPath(cl));
    194     o = cl.getParent();
    195       }
    196       return list.nreverse();
     263            LispObject list = NIL;
     264            Object o = classloader.javaInstance();
     265            while(o instanceof ClassLoader) {
     266                ClassLoader cl = (ClassLoader) o;
     267                list = list.push(dumpClassPath(cl));
     268                o = cl.getParent();
     269            }
     270            return list.nreverse();
    197271        }
    198272    };
     
    222296        @Override
    223297        public LispObject execute(LispObject jarOrJars) {
    224       return execute(jarOrJars, new JavaObject(getCurrentClassLoader()));
     298            return execute(jarOrJars, new JavaObject(getCurrentClassLoader()));
    225299        }
    226300
    227301        @Override
    228302        public LispObject execute(LispObject jarOrJars, LispObject classloader) {
    229       Object o = classloader.javaInstance();
    230       if(o instanceof JavaClassLoader) {
    231     JavaClassLoader jcl = (JavaClassLoader) o;
    232     if(jarOrJars instanceof Cons) {
    233         while(jarOrJars != NIL) {
    234       addURL(jcl, jarOrJars.car());
    235       jarOrJars = jarOrJars.cdr();
    236         }
    237     } else {
    238         addURL(jcl, jarOrJars);
    239     }
    240     return T;
    241       } else {
    242     return error(new TypeError(o + " must be an instance of " + JavaClassLoader.class.getName()));
    243       }
     303            Object o = classloader.javaInstance();
     304            if(o instanceof JavaClassLoader) {
     305                JavaClassLoader jcl = (JavaClassLoader) o;
     306                if(jarOrJars instanceof Cons) {
     307                    while(jarOrJars != NIL) {
     308                        addURL(jcl, jarOrJars.car());
     309                        jarOrJars = jarOrJars.cdr();
     310                    }
     311                } else {
     312                    addURL(jcl, jarOrJars);
     313                }
     314                return T;
     315            } else {
     316                return error(new TypeError(o + " must be an instance of " + JavaClassLoader.class.getName()));
     317            }
    244318        }
    245319    };
     
    257331
    258332    public static LispObject dumpClassPath(ClassLoader o) {
    259   if(o instanceof URLClassLoader) {
    260       LispObject list = NIL;
    261       for(URL u : ((URLClassLoader) o).getURLs()) {
    262     list = list.push(new Pathname(u));
    263       }
    264       return new Cons(new JavaObject(o), list.nreverse());
    265   } else {
    266       return new JavaObject(o);
    267   }
     333        if(o instanceof URLClassLoader) {
     334            LispObject list = NIL;
     335            for(URL u : ((URLClassLoader) o).getURLs()) {
     336                list = list.push(new Pathname(u));
     337            }
     338            return new Cons(new JavaObject(o), list.nreverse());
     339        } else {
     340            return new JavaObject(o);
     341        }
    268342    }
    269343
    270344    public static ClassLoader getCurrentClassLoader() {
    271   LispObject classLoader = CLASSLOADER.symbolValueNoThrow();
    272   if(classLoader != null) {
    273       return (ClassLoader) classLoader.javaInstance(ClassLoader.class);
    274   } else {
    275       return Lisp.class.getClassLoader();
    276   }
     345        LispObject classLoader = CLASSLOADER.symbolValueNoThrow();
     346        if(classLoader != null) {
     347            return (ClassLoader) classLoader.javaInstance(ClassLoader.class);
     348        } else {
     349            return Lisp.class.getClassLoader();
     350        }
    277351    }
    278352
  • trunk/abcl/src/org/armedbear/lisp/MemoryClassLoader.java

    r13710 r14015  
    7979            }
    8080        }
     81       
     82        if (checkPreCompiledClassLoader) {
     83            Class<?> c = findPrecompiledClassOrNull(name);
     84            if (c != null) {
     85                return c;     
     86            }
     87        }
    8188
    8289        // Fall through to our super's default handling
     
    8794    protected Class<?> findClass(String name) throws ClassNotFoundException {
    8895        try {
     96            if (checkPreCompiledClassLoader) {
     97                Class<?> c = findPrecompiledClassOrNull(name);
     98                if (c != null)
     99                        return c;                       
     100            }
    89101            byte[] b = getFunctionClassBytes(name);
    90             return defineClass(name, b, 0, b.length);
     102            return defineLispClass(name, b, 0, b.length);
    91103        } catch(Throwable e) { //TODO handle this better, readFunctionBytes uses Debug.assert() but should return null
    92104            e.printStackTrace();
     
    97109
    98110    public byte[] getFunctionClassBytes(String name) {
    99         return (byte[])hashtable.get(name).javaInstance();
    100     }
    101 
    102     public byte[] getFunctionClassBytes(Class<?> functionClass) {
    103         return getFunctionClassBytes(functionClass.getName());
    104     }
    105 
    106     public byte[] getFunctionClassBytes(Function f) {
    107         byte[] b = getFunctionClassBytes(f.getClass());
    108         f.setClassBytes(b);
    109         return b;
     111        if (hashtable.containsKey(name)) {
     112            return (byte[])hashtable.get(name).javaInstance();
     113        }
     114        return super.getFunctionClassBytes(name);
    110115    }
    111116
    112117    public LispObject loadFunction(String name) {
    113118        try {
    114             Function f = (Function) loadClass(name).newInstance();
    115             f.setClassBytes(getFunctionClassBytes(name));
     119            Class clz = loadClass(name);
     120            Function f = (Function) clz.newInstance();
     121            getFunctionClassBytes(f); //as a side effect it sets them
    116122            return f;
    117123        } catch(Throwable e) {
     
    136142    private static final Primitive PUT_MEMORY_FUNCTION = new pf_put_memory_function();
    137143    private static final class pf_put_memory_function extends Primitive {
    138   pf_put_memory_function() {
     144        pf_put_memory_function() {
    139145            super("put-memory-function", PACKAGE_SYS, false, "loader class-name class-bytes");
    140146        }
     
    143149        public LispObject execute(LispObject loader, LispObject className, LispObject classBytes) {
    144150            MemoryClassLoader l = (MemoryClassLoader) loader.javaInstance(MemoryClassLoader.class);
    145       return (LispObject)l.hashtable.put(className.getStringValue(), (JavaObject)classBytes);
     151            return (LispObject)l.hashtable.put(className.getStringValue(), (JavaObject)classBytes);
    146152        }
    147153    };
     
    149155    private static final Primitive GET_MEMORY_FUNCTION = new pf_get_memory_function();
    150156    private static final class pf_get_memory_function extends Primitive {
    151   pf_get_memory_function() {
     157        pf_get_memory_function() {
    152158            super("get-memory-function", PACKAGE_SYS, false, "loader class-name");
    153159        }
     
    156162        public LispObject execute(LispObject loader, LispObject name) {
    157163            MemoryClassLoader l = (MemoryClassLoader) loader.javaInstance(MemoryClassLoader.class);
    158       return l.loadFunction(name.getStringValue());
     164            return l.loadFunction(name.getStringValue());
    159165        }
    160166    };
     167}
    161168
    162 
    163 }
Note: See TracChangeset for help on using the changeset viewer.