/* * Copyright (c) 2007, 2011, 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.sun.max.vm.hosted; import java.lang.reflect.*; import sun.misc.*; import com.sun.max.program.*; /** * Bypass access checks for reflective operations. */ public final class WithoutAccessCheck { public static final Unsafe unsafe = (Unsafe) getStaticField(Unsafe.class, "theUnsafe"); private WithoutAccessCheck() { } private static Field findField(Class javaClass, String fieldName) { Class c = javaClass; while (c != null) { try { final Field field = c.getDeclaredField(fieldName); field.setAccessible(true); return field; } catch (NoSuchFieldException noSuchFieldException) { } c = c.getSuperclass(); } throw ProgramError.unexpected("could not find field " + fieldName); } private static void accessError(Field field) { throw new IllegalAccessError("could not access field " + field); } public static Object getInstanceField(Object tuple, String fieldName) { final Field field = findField(tuple.getClass(), fieldName); try { return field.get(tuple); } catch (IllegalAccessException illegalAccessException) { accessError(field); return null; } } public static void setInstanceField(Object tuple, String fieldName, Object value) { final Field field = findField(tuple.getClass(), fieldName); try { field.set(tuple, value); } catch (IllegalAccessException illegalAccessException) { accessError(field); } } public static Object getStaticField(Class javaClass, String fieldName) { final Field field = findField(javaClass, fieldName); try { return field.get(javaClass); } catch (IllegalAccessException illegalAccessException) { accessError(field); return null; } } public static void setStaticField(Class javaClass, String fieldName, Object value) { final Field field = findField(javaClass, fieldName); try { field.set(javaClass, value); } catch (IllegalAccessException illegalAccessException) { accessError(field); } } public static Object newInstance(Class<?> javaClass) { try { final Constructor constructor = javaClass.getDeclaredConstructor(); constructor.setAccessible(true); return constructor.newInstance(); } catch (Exception e) { throw ProgramError.unexpected(e); } } /** * Return the named method with a method signature matching parameter classes from the given class. */ private static Method getMethod(Class<?> instanceClass, String methodName, Class[] parameterClasses) throws NoSuchMethodException { if (instanceClass == null) { throw new NoSuchMethodException("Invalid method : " + methodName); } try { final Method declaredMethod = instanceClass.getDeclaredMethod(methodName, parameterClasses); return declaredMethod; } catch (NoSuchMethodException noSuchMethodException) { return getMethod(instanceClass.getSuperclass(), methodName, parameterClasses); } } private static Class getWrapperClass(Class primitiveClass) { assert primitiveClass.isPrimitive(); String name = primitiveClass.getName(); if (name.equals("int")) { name = "Integer"; } else if (name.equals("char")) { name = "Character"; } else { name = Character.toUpperCase(name.charAt(0)) + name.substring(1); } try { return Class.forName("java.lang." + name); } catch (Throwable throwable) { throw ProgramError.unexpected(); } } private static boolean compatible(Class parameterClass, Object argument) { if (parameterClass == null) { return false; } if (parameterClass.isPrimitive()) { if (argument == null) { return false; } return getWrapperClass(parameterClass).isInstance(argument); } else if (argument == null) { return true; } return parameterClass.isInstance(argument); } private static boolean compatible(Class[] parameterClasses, Object[] arguments) { if (arguments == null) { return parameterClasses == null; } if (parameterClasses.length != arguments.length) { return false; } for (int i = 0; i < parameterClasses.length; i++) { if (!compatible(parameterClasses[i], arguments[i])) { return false; } } return true; } /** * Calls a method on the given object instance with the given arguments. */ public static Object invokeVirtual(Object instance, String methodName, Class[] parameterClasses, Object[] arguments) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { assert compatible(parameterClasses, arguments); final Method method = getMethod(instance.getClass(), methodName, parameterClasses); method.setAccessible(true); return method.invoke(instance, arguments); } public static Object invokeStatic(Class instanceClass, String methodName, Class[] parameterClasses, Object[] arguments) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { assert compatible(parameterClasses, arguments); final Method method = getMethod(instanceClass, methodName, parameterClasses); method.setAccessible(true); return method.invoke(null, arguments); } public static Object invokeConstructor(Class<?> instanceClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { final Constructor constructor = instanceClass.getDeclaredConstructor(new Class[]{}); constructor.setAccessible(true); return constructor.newInstance(new Object[]{}); } }