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 proto...@googlegroups.com.
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.

Reply via email to