8038343: Eliminate use of reflection to access JavaBeans Introspector
Reviewed-by: mchung, malenkov
This commit is contained in:
parent
0c0e4775d4
commit
b7a4487e54
jdk/src/share/classes
com/sun/jmx/mbeanserver
java/beans
sun/misc
@ -55,6 +55,9 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
|
||||
import sun.misc.JavaBeansIntrospectorAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
@ -549,16 +552,9 @@ public class Introspector {
|
||||
// Java Beans introspection
|
||||
//
|
||||
Class<?> clazz = complex.getClass();
|
||||
Method readMethod = null;
|
||||
if (BeansHelper.isAvailable()) {
|
||||
Object bi = BeansHelper.getBeanInfo(clazz);
|
||||
Object[] pds = BeansHelper.getPropertyDescriptors(bi);
|
||||
for (Object pd: pds) {
|
||||
if (BeansHelper.getPropertyName(pd).equals(element)) {
|
||||
readMethod = BeansHelper.getReadMethod(pd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Method readMethod;
|
||||
if (BeansIntrospector.isAvailable()) {
|
||||
readMethod = BeansIntrospector.getReadMethod(clazz, element);
|
||||
} else {
|
||||
// Java Beans not available so use simple introspection
|
||||
// to locate method
|
||||
@ -583,6 +579,30 @@ public class Introspector {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to java.beans.Introspector if available.
|
||||
*/
|
||||
private static class BeansIntrospector {
|
||||
private static final JavaBeansIntrospectorAccess JBIA;
|
||||
static {
|
||||
// ensure that java.beans.Introspector is initialized (if present)
|
||||
try {
|
||||
Class.forName("java.beans.Introspector", true,
|
||||
BeansIntrospector.class.getClassLoader());
|
||||
} catch (ClassNotFoundException ignore) { }
|
||||
|
||||
JBIA = SharedSecrets.getJavaBeansIntrospectorAccess();
|
||||
}
|
||||
|
||||
static boolean isAvailable() {
|
||||
return JBIA != null;
|
||||
}
|
||||
|
||||
static Method getReadMethod(Class<?> clazz, String property) throws Exception {
|
||||
return JBIA.getReadMethod(clazz, property);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple introspector that uses reflection to analyze a class and
|
||||
* identify its "getter" methods. This class is intended for use only when
|
||||
@ -696,121 +716,4 @@ public class Introspector {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that provides access to the JavaBeans Introspector and
|
||||
* PropertyDescriptors without creating a static dependency on java.beans.
|
||||
*/
|
||||
private static class BeansHelper {
|
||||
private static final Class<?> introspectorClass =
|
||||
getClass("java.beans.Introspector");
|
||||
private static final Class<?> beanInfoClass =
|
||||
(introspectorClass == null) ? null : getClass("java.beans.BeanInfo");
|
||||
private static final Class<?> getPropertyDescriptorClass =
|
||||
(beanInfoClass == null) ? null : getClass("java.beans.PropertyDescriptor");
|
||||
|
||||
private static final Method getBeanInfo =
|
||||
getMethod(introspectorClass, "getBeanInfo", Class.class);
|
||||
private static final Method getPropertyDescriptors =
|
||||
getMethod(beanInfoClass, "getPropertyDescriptors");
|
||||
private static final Method getPropertyName =
|
||||
getMethod(getPropertyDescriptorClass, "getName");
|
||||
private static final Method getReadMethod =
|
||||
getMethod(getPropertyDescriptorClass, "getReadMethod");
|
||||
|
||||
private static Class<?> getClass(String name) {
|
||||
try {
|
||||
return Class.forName(name, true, null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static Method getMethod(Class<?> clazz,
|
||||
String name,
|
||||
Class<?>... paramTypes)
|
||||
{
|
||||
if (clazz != null) {
|
||||
try {
|
||||
return clazz.getMethod(name, paramTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private BeansHelper() { }
|
||||
|
||||
/**
|
||||
* Returns {@code true} if java.beans is available.
|
||||
*/
|
||||
static boolean isAvailable() {
|
||||
return introspectorClass != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.Introspector.getBeanInfo(Class)
|
||||
*/
|
||||
static Object getBeanInfo(Class<?> clazz) throws Exception {
|
||||
try {
|
||||
return getBeanInfo.invoke(null, clazz);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof Exception)
|
||||
throw (Exception)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.BeanInfo.getPropertyDescriptors()
|
||||
*/
|
||||
static Object[] getPropertyDescriptors(Object bi) {
|
||||
try {
|
||||
return (Object[])getPropertyDescriptors.invoke(bi);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof RuntimeException)
|
||||
throw (RuntimeException)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.PropertyDescriptor.getName()
|
||||
*/
|
||||
static String getPropertyName(Object pd) {
|
||||
try {
|
||||
return (String)getPropertyName.invoke(pd);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof RuntimeException)
|
||||
throw (RuntimeException)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.PropertyDescriptor.getReadMethod()
|
||||
*/
|
||||
static Method getReadMethod(Object pd) {
|
||||
try {
|
||||
return (Method)getReadMethod.invoke(pd);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof RuntimeException)
|
||||
throw (RuntimeException)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,8 @@ import java.util.EventObject;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import sun.misc.JavaBeansIntrospectorAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
@ -140,6 +142,20 @@ public class Introspector {
|
||||
static final String SET_PREFIX = "set";
|
||||
static final String IS_PREFIX = "is";
|
||||
|
||||
// register with SharedSecrets for JMX usage
|
||||
static {
|
||||
SharedSecrets.setJavaBeansIntrospectorAccess((clazz, property) -> {
|
||||
BeanInfo bi = Introspector.getBeanInfo(clazz);
|
||||
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
|
||||
for (PropertyDescriptor pd: pds) {
|
||||
if (pd.getName().equals(property)) {
|
||||
return pd.getReadMethod();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Public methods
|
||||
//======================================================================
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 sun.misc;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public interface JavaBeansIntrospectorAccess {
|
||||
Method getReadMethod(Class<?> clazz, String property) throws Exception;
|
||||
}
|
@ -55,6 +55,7 @@ public class SharedSecrets {
|
||||
private static JavaSecurityAccess javaSecurityAccess;
|
||||
private static JavaUtilZipFileAccess javaUtilZipFileAccess;
|
||||
private static JavaAWTAccess javaAWTAccess;
|
||||
private static JavaBeansIntrospectorAccess javaBeansIntrospectorAccess;
|
||||
|
||||
public static JavaUtilJarAccess javaUtilJarAccess() {
|
||||
if (javaUtilJarAccess == null) {
|
||||
@ -184,4 +185,12 @@ public class SharedSecrets {
|
||||
}
|
||||
return javaAWTAccess;
|
||||
}
|
||||
|
||||
public static JavaBeansIntrospectorAccess getJavaBeansIntrospectorAccess() {
|
||||
return javaBeansIntrospectorAccess;
|
||||
}
|
||||
|
||||
public static void setJavaBeansIntrospectorAccess(JavaBeansIntrospectorAccess access) {
|
||||
javaBeansIntrospectorAccess = access;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user