changeset 23328:d6cbb275d6ce

Ignore AccessControlExceptions when trying to use ASM from the JDK
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Fri, 18 Mar 2016 12:47:49 -0700
parents 19c85f6618ed
children bc5552dc384b
files jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java
diffstat 1 files changed, 85 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java	Fri Mar 18 10:51:08 2016 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java	Fri Mar 18 12:47:49 2016 -0700
@@ -30,6 +30,7 @@
 import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.security.AccessControlException;
 import java.util.Arrays;
 import java.util.Objects;
 
@@ -43,13 +44,13 @@
 import sun.misc.Unsafe;
 
 /**
- * A {@link ClassVisitor} that verifies {@link HotSpotVMConfig} does not access {@link Unsafe} from
- * any of its non-static, non-constructor methods. This ensures that a deserialized
- * {@link HotSpotVMConfig} object does not perform any unsafe reads on addresses that are only valid
- * in the context in which the object was serialized. Note that this does not catch cases where a
- * client uses an address stored in a {@link HotSpotVMConfig} field.
+ * A verifier that checks that {@link HotSpotVMConfig} does not access {@link Unsafe} from any of
+ * its non-static, non-constructor methods. This ensures that a deserialized {@link HotSpotVMConfig}
+ * object does not perform any unsafe reads on addresses that are only valid in the context in which
+ * the object was serialized. Note that this does not catch cases where a client uses an address
+ * stored in a {@link HotSpotVMConfig} field.
  */
-final class HotSpotVMConfigVerifier extends ClassVisitor {
+final class HotSpotVMConfigVerifier {
 
     public static boolean check() {
         Class<?> cls = HotSpotVMConfig.class;
@@ -57,24 +58,20 @@
         try {
             InputStream classfile = cls.getResourceAsStream(classFilePath);
             ClassReader cr = new ClassReader(Objects.requireNonNull(classfile, "Could not find class file for " + cls.getName()));
-            ClassVisitor cv = new HotSpotVMConfigVerifier();
+            ClassVisitor cv = new Verifier();
             cr.accept(cv, 0);
             return true;
+        } catch (AccessControlException e) {
+            /*
+             * When running with a security manager and +UseJVMCIClassLoader the ASM classes might
+             * not be accessible.
+             */
+            return true;
         } catch (IOException e) {
             throw new JVMCIError(e);
         }
     }
 
-    /**
-     * Source file context for error reporting.
-     */
-    String sourceFile = null;
-
-    /**
-     * Line number for error reporting.
-     */
-    int lineNo = -1;
-
     private static Class<?> resolve(String name) {
         try {
             return Class.forName(name.replace('/', '.'));
@@ -83,82 +80,95 @@
         }
     }
 
-    HotSpotVMConfigVerifier() {
-        super(Opcodes.ASM5);
-    }
+    private static class Verifier extends ClassVisitor {
 
-    @Override
-    public void visitSource(String source, String debug) {
-        this.sourceFile = source;
-    }
+        /**
+         * Source file context for error reporting.
+         */
+        String sourceFile = null;
+
+        /**
+         * Line number for error reporting.
+         */
+        int lineNo = -1;
 
-    void verify(boolean condition, String message) {
-        if (!condition) {
-            error(message);
+        Verifier() {
+            super(Opcodes.ASM5);
         }
-    }
 
-    void error(String message) {
-        String errorMessage = format("%s:%d: %s is not allowed in the context of compilation replay. The unsafe access should be moved into the %s constructor and the result cached in a field",
-                        sourceFile, lineNo, message, HotSpotVMConfig.class.getSimpleName());
-        throw new JVMCIError(errorMessage);
+        @Override
+        public void visitSource(String source, String debug) {
+            this.sourceFile = source;
+        }
 
-    }
+        void verify(boolean condition, String message) {
+            if (!condition) {
+                error(message);
+            }
+        }
 
-    @Override
-    public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) {
-        if (!Modifier.isStatic(access) && Modifier.isPublic(access) && !name.equals("<init>")) {
-            return new MethodVisitor(Opcodes.ASM5) {
+        void error(String message) {
+            String errorMessage = format("%s:%d: %s is not allowed in the context of compilation replay. The unsafe access should be moved into the %s constructor and the result cached in a field",
+                            sourceFile, lineNo, message, HotSpotVMConfig.class.getSimpleName());
+            throw new JVMCIError(errorMessage);
+
+        }
 
-                @Override
-                public void visitLineNumber(int line, Label start) {
-                    lineNo = line;
-                }
+        @Override
+        public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) {
+            if (!Modifier.isStatic(access) && Modifier.isPublic(access) && !name.equals("<init>")) {
+                return new MethodVisitor(Opcodes.ASM5) {
+
+                    @Override
+                    public void visitLineNumber(int line, Label start) {
+                        lineNo = line;
+                    }
 
-                private Executable resolveMethod(String owner, String methodName, String methodDesc) {
-                    Class<?> declaringClass = resolve(owner);
-                    while (declaringClass != null) {
-                        if (methodName.equals("<init>")) {
-                            for (Constructor<?> c : declaringClass.getDeclaredConstructors()) {
-                                if (methodDesc.equals(Type.getConstructorDescriptor(c))) {
-                                    return c;
+                    private Executable resolveMethod(String owner, String methodName, String methodDesc) {
+                        Class<?> declaringClass = resolve(owner);
+                        while (declaringClass != null) {
+                            if (methodName.equals("<init>")) {
+                                for (Constructor<?> c : declaringClass.getDeclaredConstructors()) {
+                                    if (methodDesc.equals(Type.getConstructorDescriptor(c))) {
+                                        return c;
+                                    }
                                 }
-                            }
-                        } else {
-                            Type[] argumentTypes = Type.getArgumentTypes(methodDesc);
-                            for (Method m : declaringClass.getDeclaredMethods()) {
-                                if (m.getName().equals(methodName)) {
-                                    if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) {
-                                        if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) {
-                                            return m;
+                            } else {
+                                Type[] argumentTypes = Type.getArgumentTypes(methodDesc);
+                                for (Method m : declaringClass.getDeclaredMethods()) {
+                                    if (m.getName().equals(methodName)) {
+                                        if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) {
+                                            if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) {
+                                                return m;
+                                            }
                                         }
                                     }
                                 }
                             }
+                            declaringClass = declaringClass.getSuperclass();
                         }
-                        declaringClass = declaringClass.getSuperclass();
+                        throw new NoSuchMethodError(owner + "." + methodName + methodDesc);
                     }
-                    throw new NoSuchMethodError(owner + "." + methodName + methodDesc);
-                }
 
-                /**
-                 * Checks whether a given method is allowed to be called.
-                 */
-                private boolean checkInvokeTarget(Executable method) {
-                    if (method.getDeclaringClass().equals(Unsafe.class)) {
-                        return false;
+                    /**
+                     * Checks whether a given method is allowed to be called.
+                     */
+                    private boolean checkInvokeTarget(Executable method) {
+                        if (method.getDeclaringClass().equals(Unsafe.class)) {
+                            return false;
+                        }
+                        return true;
                     }
-                    return true;
-                }
 
-                @Override
-                public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) {
-                    Executable callee = resolveMethod(owner, methodName, methodDesc);
-                    verify(checkInvokeTarget(callee), "invocation of " + callee);
-                }
-            };
-        } else {
-            return null;
+                    @Override
+                    public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) {
+                        Executable callee = resolveMethod(owner, methodName, methodDesc);
+                        verify(checkInvokeTarget(callee), "invocation of " + callee);
+                    }
+                };
+            } else {
+                return null;
+            }
         }
     }
 }