Mercurial > hg > truffle
diff test/compiler/jsr292/methodHandleExceptions/ByteClassLoader.java @ 13403:9d15b81d5d1b
8016839: JSR292: AME instead of IAE when calling a method
Summary: Catch missing-because-illegal case for itable entries and use an exception-throwing method instead of null.
Reviewed-by: acorn, jrose, coleenp
author | drchase |
---|---|
date | Tue, 26 Nov 2013 18:16:04 -0500 |
parents | dc261f466b6d |
children |
line wrap: on
line diff
--- a/test/compiler/jsr292/methodHandleExceptions/ByteClassLoader.java Fri Nov 22 13:42:46 2013 -0800 +++ b/test/compiler/jsr292/methodHandleExceptions/ByteClassLoader.java Tue Nov 26 18:16:04 2013 -0500 @@ -1,3 +1,12 @@ +import java.io.BufferedOutputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + /* * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -23,12 +32,63 @@ */ /** - * A minimal classloader for loading bytecodes that could not result from - * properly compiled Java. + * A ByteClassLoader is used to define classes from collections of bytes, as + * well as loading classes in the usual way. It includes options to write the + * classes to files in a jar, or to read the classes from jars in a later or + * debugging run. + * + * If Boolean property byteclassloader.verbose is true, be chatty about jar + * file operations. * - * @author dr2chase */ -public class ByteClassLoader extends ClassLoader { +public class ByteClassLoader extends URLClassLoader { + + final static boolean verbose + = Boolean.getBoolean("byteclassloader.verbose"); + + final boolean read; + final JarOutputStream jos; + final String jar_name; + + /** + * Make a new ByteClassLoader. + * + * @param jar_name Basename of jar file to be read/written by this classloader. + * @param read If true, read classes from jar file instead of from parameter. + * @param write If true, write classes to jar files for offline study/use. + * + * @throws FileNotFoundException + * @throws IOException + */ + public ByteClassLoader(String jar_name, boolean read, boolean write) + throws FileNotFoundException, IOException { + super(read + ? new URL[]{new URL("file:" + jar_name + ".jar")} + : new URL[0]); + this.read = read; + this.jar_name = jar_name; + this.jos = write + ? new JarOutputStream( + new BufferedOutputStream( + new FileOutputStream(jar_name + ".jar"))) : null; + if (read && write) { + throw new Error("At most one of read and write may be true."); + } + } + + private static void writeJarredFile(JarOutputStream jos, String file, String suffix, byte[] bytes) { + String fileName = file.replace(".", "/") + "." + suffix; + JarEntry ze = new JarEntry(fileName); + try { + ze.setSize(bytes.length); + jos.putNextEntry(ze); + jos.write(bytes); + jos.closeEntry(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + /** * (pre)load class name using classData for the definition. * @@ -36,9 +96,36 @@ * @param classData * @return */ - public Class<?> loadBytes(String name, byte[] classData) { - Class<?> clazz = defineClass(name, classData, 0, classData.length); - resolveClass(clazz); - return clazz; + public Class<?> loadBytes(String name, byte[] classData) throws ClassNotFoundException { + if (jos != null) { + if (verbose) { + System.out.println("ByteClassLoader: writing " + name); + } + writeJarredFile(jos, name, "class", classData); + } + + Class<?> clazz = null; + if (read) { + if (verbose) { + System.out.println("ByteClassLoader: reading " + name + " from " + jar_name); + } + clazz = loadClass(name); + } else { + clazz = defineClass(name, classData, 0, classData.length); + resolveClass(clazz); + } + return clazz; + } + + public void close() { + if (jos != null) { + try { + if (verbose) { + System.out.println("ByteClassLoader: closing " + jar_name); + } + jos.close(); + } catch (IOException ex) { + } + } } }