changeset 5626:4967be7265bc

Added BootImageClassLoader and associated test class.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 14 Jun 2012 17:54:59 +0200
parents 102f87543d5e
children e1b29c516354
files graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BootImageClassLoaderTest.java graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageClassLoader.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java
diffstat 4 files changed, 188 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BootImageClassLoaderTest.java	Thu Jun 14 17:54:59 2012 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.boot;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+
+public class BootImageClassLoaderTest {
+
+    @Test
+    public void test() throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException, SecurityException {
+
+        TestClassB.x = 1;
+        BootImageClassLoader l = new BootImageClassLoader();
+
+        // Assert that the class definition is really duplicated.
+        Class<?> bClass = Class.forName(TestClassB.class.getCanonicalName(), true, l);
+        Assert.assertNotSame(TestClassB.class, bClass);
+
+        // Assert that the class definition is not duplicated more than once.
+        Assert.assertSame(bClass, l.convert(TestClassB.class));
+
+        // Set field x such that it is used by the subsequent static initializer for TestClassA.
+        Field bField = bClass.getFields()[0];
+        bField.setAccessible(true);
+        bField.set(null, 2);
+
+        // Assert that the class definition is duplicated.
+        Class<?> aClass = l.convert(TestClassA.class);
+        Assert.assertNotSame(TestClassA.class, aClass);
+
+        // Assert that the original version of TestClassA was initialized correctly.
+        Assert.assertEquals(1, TestClassA.x);
+
+        // Assert that the duplicated version of TestClassA was initialized correctly.
+        Field aField = aClass.getFields()[0];
+        aField.setAccessible(true);
+        Assert.assertEquals(2, aField.getInt(null));
+
+        // Assert that system classes are not duplicated.
+        Assert.assertSame(Object.class, l.convert(Object.class));
+        Assert.assertSame(Object.class, Class.forName(Object.class.getCanonicalName(), true, l));
+    }
+
+}
+
+class TestClassA {
+    public static int x;
+
+    static {
+        x = TestClassB.x;
+    }
+}
+
+class TestClassB {
+    public static int x;
+}
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java	Mon Jun 11 17:06:06 2012 +0200
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java	Thu Jun 14 17:54:59 2012 +0200
@@ -22,7 +22,25 @@
  */
 package com.oracle.graal.boot;
 
+import java.io.*;
+import java.lang.reflect.*;
+
+import com.oracle.graal.boot.test.helloworld.*;
+
 
 public class HelloWorldTest {
+    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IOException {
+        Method entryPoint = HelloWorldTestProgram.class.getMethod("main", String[].class);
+        System.out.println(HelloWorldTestProgram.class.getCanonicalName());
+        InputStream inputStream = HelloWorldTestProgram.class.getClassLoader().getResourceAsStream(HelloWorldTestProgram.class.getName().replace('.', '/').concat(".class"));
 
+        byte[] byteCodes = new byte[inputStream.available()];
+        inputStream.read(byteCodes);
+        System.out.println(byteCodes);
+        ClassLoader l = new ClassLoader() {
+
+
+        };
+
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageClassLoader.java	Thu Jun 14 17:54:59 2012 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.boot;
+
+import java.io.*;
+
+public class BootImageClassLoader extends ClassLoader {
+
+    @Override
+    protected java.lang.Class< ? > loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        synchronized (getClassLoadingLock(name)) {
+            Class< ? > result = findLoadedClass(name);
+            if (result == null) {
+                result = super.loadClass(name, resolve);
+                assert result.getName().equals(name);
+                return duplicate(result);
+            }
+            return result;
+        }
+    }
+
+    private Class< ? > duplicate(Class< ? > result) {
+        // This is a class in the bootclasspath => share.
+        if (result.getClassLoader() == null) {
+            return result;
+        }
+
+        // Duplicate class definition.
+        InputStream inputStream = result.getClassLoader().getResourceAsStream(result.getName().replace('.', '/').concat(".class"));
+        try {
+            byte[] byteCodes = new byte[inputStream.available()];
+            inputStream.read(byteCodes);
+            return this.defineClass(result.getName(), byteCodes, 0, byteCodes.length);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not access class bytes for " + result.getName());
+        }
+    }
+
+    public Class< ? > convert(Class< ? > clazz) {
+        synchronized (getClassLoadingLock(clazz.getCanonicalName())) {
+            // This class has this class loader => no conversion necessary.
+            if (clazz.getClassLoader() == this) {
+                return clazz;
+            }
+
+            Class< ? > thisClazz = findLoadedClass(clazz.getName());
+            if (thisClazz != null) {
+                return thisClazz;
+            }
+
+            return duplicate(clazz);
+        }
+    }
+}
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java	Mon Jun 11 17:06:06 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java	Thu Jun 14 17:54:59 2012 +0200
@@ -22,7 +22,24 @@
  */
 package com.oracle.graal.boot;
 
+import java.lang.reflect.*;
+
+import com.oracle.graal.debug.*;
+
 
 public class BootImageGenerator {
 
+    private final BootImageClassLoader classLoader = new BootImageClassLoader();
+
+    public void addEntryMethod(Class<?> clazz, String name, Class<?> ... parameterTypes) {
+        Class<?> convertedClass = classLoader.convert(clazz);
+        Method method;
+        try {
+            method = convertedClass.getDeclaredMethod(name, parameterTypes);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException("Could not find method " + name + " with parameter types " + parameterTypes + " in class " + convertedClass.getCanonicalName());
+        }
+        Debug.log("Adding method %s.%s to the boot image", method.getClass().getName(), method.getName());
+    }
+
 }