Please don't use reflection to reach into private internals of classes you don't maintain. We have "public" and "private" for a reason. Furthermore, this access may throw a SecurityException if a SecurityManager is in use.
On Mon, May 31, 2010 at 11:25 AM, David Dabbs <[email protected]> wrote: > > The approach I found worked the best: > > 1. Copy the string into a pre-allocated and re-used char[] array. This > is needed since the JDK does not permit access to the String's > char[] ,to enforce immutability. This is a performance "loss" VS the > JDK, which can access the char[] directly.... > > > Evan, > > you may access a String's internals via reflection in a "safe," albeit > potentially implementation-specific way. See class code below. > As long as your java.lang.String uses "value" for the char[] and > "offset" for the storage offset, this should work. > No sun.misc.Unsafe used. Only tested/used on JDK6. > > > David > > > > /*************************************************************************** > **********/ > import java.lang.reflect.*; > > > public final class ReflectionUtils { > > /** > * There is no explicit Modifier constant for package-privete, so 0 is > used. > */ > public static final int MODIFIER_PACKAGE_PRIVATE = 0x00000000; > > > /** Field object for accessing Sting::value character storage. */ > public static final Field STRING_VALUE_FIELD = > getFieldAccessible(String.class, "value"); > > > /** Field object for accessing Sting::offset, the first index used in > the value[] char storage. */ > public static final Field STRING_OFFSET_FIELD = > getFieldAccessible(String.class, "offset"); > > > /** > * Package private String constructor which shares value array for > speed. > * > * Use when a number of String objects share the same char[] storage. > * > * See String(int offset, int count, char value[]). > */ > public static final Constructor<?> STRING_PP_CTOR = > getConstructor(String.class, MODIFIER_PACKAGE_PRIVATE, int.class, > int.class, > char[].class); > > > /** > * To avoid violating final field semantics, take care to only _read_ > * the char[] value returned. > */ > public static char[] getChars(final String s) { > try { > // use reflection to read the char[] value from the string. . . > return (char[]) STRING_VALUE_FIELD.get(s); > } catch (Throwable t) { > return null; > } > } > > > public static String sharedString(final char[] chars, final int offset, > final int length) { > try { > return (String) STRING_PP_CTOR.newInstance(offset, length, > chars); > } catch (InstantiationException e) { > e.printStackTrace(); > } catch (IllegalAccessException e) { > e.printStackTrace(); > } catch (InvocationTargetException e) { > e.printStackTrace(); > } catch (Throwable t) { > t.printStackTrace(); > } > return null; > } > > > public static Field getFieldAccessible(final Class<?> clazz, final > String fieldName) { > Field fld = null; > try { > fld = clazz.getDeclaredField(fieldName); > fld.setAccessible(true); > } catch (NoSuchFieldException e) { > e.printStackTrace(); > } catch (SecurityException e) { > e.printStackTrace(); > } > return fld; > } > > > public static Constructor<?> getConstructor(final Class<?> clazz, final > int searchModifier, final Class<?>... paramTypes) { > > if(clazz==null) { > throw new IllegalArgumentException("A class parameter is > required"); > } > > try { > // > // There is no explicit Modifier accessor constant for > package-privete, so 0 is used. > // > > for (Constructor<?> ctor : clazz.getDeclaredConstructors()) { > > if (searchModifier == (ctor.getModifiers() & > (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED))) { > // > // access modifier matches. . . > // > final Class<?>[] parameterTypes = > ctor.getParameterTypes(); > if (parameterTypes.length == paramTypes.length) { > // > // same number of parameters. . . > // > for (int i = 0; i < parameterTypes.length; i++) { > if (!parameterTypes[i].equals(paramTypes[i])) { > // one parameter not of correct type, so > bail. . . > // note ctor variable used as success marker > below > ctor = null; > break; > } else { > // Type[] gpType = > ctor.getGenericParameterTypes(); > // for (int j = 0; j < gpType.length; j++) { > // char ch = > (gpType[j].equals(paramTypes[i]) ? '*' : ' '); > // System.out.format("%7c%s[%d]: %s%n", > ch, "GenericParameterType", j, gpType[j]); > // } > } > } > if (ctor != null) { > // all ctor parameter types match, so call > ctor.setAccessible(true) > // System.out.format("%s%n", > ctor.toGenericString()); > // System.out.format(" [ synthetic=%-5b > var_args=%-5b ]%n", ctor.isSynthetic(), ctor.isVarArgs()); > > ctor.setAccessible(true); > return ctor; > } > } > } > } > } catch (Throwable t) { > // will return null below > } > return null; // error or ctor not found > } > > > /** > * The AccessibleObject class is the base class for Field, Method and > * Constructor objects. It provides the ability to flag a reflected > * object as suppressing default Java language access control checks > * when it is used. The access checks--for public, default (package) > * access, protected, and private members--are performed when Fields, > * Methods or Constructors are used to set or get fields, to invoke > * methods, or to create and initialize new instances of classes, > * respectively. > * > * <p>Setting the <tt>accessible</tt> flag in a reflected object > * permits sophisticated applications with sufficient privilege, such > * as Java Object Serialization or other persistence mechanisms, to > * manipulate objects in a manner that would normally be prohibited. > * > * @see AccessibleObject > * > **/ > public static boolean setAccessible(final AccessibleObject o) { > > try { > o.setAccessible(true); > return true; > } catch (Throwable /*SecurityException*/ e) { > return false; > } > } > > } > > > > -- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.
