1 /*
   2  * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  29 
  30 final class VarHandles {
  31 
  32     static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
  33         if (!f.isStatic()) {
  34             long foffset = MethodHandleNatives.objectFieldOffset(f);
  35             if (!type.isPrimitive()) {
  36                 if (f.isFlatValue()) {
  37                     return f.isFinal() && !isWriteAllowedOnFinalFields
  38                         ? new VarHandleObjects.FlatValueFieldInstanceReadOnly(refc, foffset, type)
  39                         : new VarHandleObjects.FlatValueFieldInstanceReadWrite(refc, foffset, type);
  40                 } else {
  41                     return f.isFinal() && !isWriteAllowedOnFinalFields
  42                         ? new VarHandleObjects.FieldInstanceReadOnly(refc, foffset, type)
  43                         : new VarHandleObjects.FieldInstanceReadWrite(refc, foffset, type, f.canBeNull());
  44                 }
  45             }
  46             else if (type == boolean.class) {
  47                 return f.isFinal() && !isWriteAllowedOnFinalFields
  48                        ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
  49                        : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset);
  50             }
  51             else if (type == byte.class) {
  52                 return f.isFinal() && !isWriteAllowedOnFinalFields
  53                        ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
  54                        : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset);
  55             }
  56             else if (type == short.class) {
  57                 return f.isFinal() && !isWriteAllowedOnFinalFields
  58                        ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
  59                        : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset);
  60             }
  61             else if (type == char.class) {
  62                 return f.isFinal() && !isWriteAllowedOnFinalFields
  63                        ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
  64                        : new VarHandleChars.FieldInstanceReadWrite(refc, foffset);
  65             }
  66             else if (type == int.class) {
  67                 return f.isFinal() && !isWriteAllowedOnFinalFields
  68                        ? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
  69                        : new VarHandleInts.FieldInstanceReadWrite(refc, foffset);
  70             }
  71             else if (type == long.class) {
  72                 return f.isFinal() && !isWriteAllowedOnFinalFields
  73                        ? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
  74                        : new VarHandleLongs.FieldInstanceReadWrite(refc, foffset);
  75             }
  76             else if (type == float.class) {
  77                 return f.isFinal() && !isWriteAllowedOnFinalFields
  78                        ? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
  79                        : new VarHandleFloats.FieldInstanceReadWrite(refc, foffset);
  80             }
  81             else if (type == double.class) {
  82                 return f.isFinal() && !isWriteAllowedOnFinalFields
  83                        ? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
  84                        : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset);
  85             }
  86             else {
  87                 throw new UnsupportedOperationException();
  88             }
  89         }
  90         else {
  91             // TODO This is not lazy on first invocation
  92             // and might cause some circular initialization issues
  93 
  94             // Replace with something similar to direct method handles
  95             // where a barrier is used then elided after use
  96 
  97             if (UNSAFE.shouldBeInitialized(refc))
  98                 UNSAFE.ensureClassInitialized(refc);
  99 
 100             Object base = MethodHandleNatives.staticFieldBase(f);
 101             long foffset = MethodHandleNatives.staticFieldOffset(f);
 102             if (!type.isPrimitive()) {
 103                 assert(!f.isFlatValue());   // static field is not flattened
 104                 return f.isFinal() && !isWriteAllowedOnFinalFields
 105                         ? new VarHandleObjects.FieldStaticReadOnly(base, foffset, type)
 106                         : new VarHandleObjects.FieldStaticReadWrite(base, foffset, type, f.canBeNull());
 107             }
 108             else if (type == boolean.class) {
 109                 return f.isFinal() && !isWriteAllowedOnFinalFields
 110                        ? new VarHandleBooleans.FieldStaticReadOnly(base, foffset)
 111                        : new VarHandleBooleans.FieldStaticReadWrite(base, foffset);
 112             }
 113             else if (type == byte.class) {
 114                 return f.isFinal() && !isWriteAllowedOnFinalFields
 115                        ? new VarHandleBytes.FieldStaticReadOnly(base, foffset)
 116                        : new VarHandleBytes.FieldStaticReadWrite(base, foffset);
 117             }
 118             else if (type == short.class) {
 119                 return f.isFinal() && !isWriteAllowedOnFinalFields
 120                        ? new VarHandleShorts.FieldStaticReadOnly(base, foffset)
 121                        : new VarHandleShorts.FieldStaticReadWrite(base, foffset);
 122             }
 123             else if (type == char.class) {
 124                 return f.isFinal() && !isWriteAllowedOnFinalFields
 125                        ? new VarHandleChars.FieldStaticReadOnly(base, foffset)
 126                        : new VarHandleChars.FieldStaticReadWrite(base, foffset);
 127             }
 128             else if (type == int.class) {
 129                 return f.isFinal() && !isWriteAllowedOnFinalFields
 130                        ? new VarHandleInts.FieldStaticReadOnly(base, foffset)
 131                        : new VarHandleInts.FieldStaticReadWrite(base, foffset);
 132             }
 133             else if (type == long.class) {
 134                 return f.isFinal() && !isWriteAllowedOnFinalFields
 135                        ? new VarHandleLongs.FieldStaticReadOnly(base, foffset)
 136                        : new VarHandleLongs.FieldStaticReadWrite(base, foffset);
 137             }
 138             else if (type == float.class) {
 139                 return f.isFinal() && !isWriteAllowedOnFinalFields
 140                        ? new VarHandleFloats.FieldStaticReadOnly(base, foffset)
 141                        : new VarHandleFloats.FieldStaticReadWrite(base, foffset);
 142             }
 143             else if (type == double.class) {
 144                 return f.isFinal() && !isWriteAllowedOnFinalFields
 145                        ? new VarHandleDoubles.FieldStaticReadOnly(base, foffset)
 146                        : new VarHandleDoubles.FieldStaticReadWrite(base, foffset);
 147             }
 148             else {
 149                 throw new UnsupportedOperationException();
 150             }
 151         }
 152     }
 153 
 154     static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
 155         if (!arrayClass.isArray())
 156             throw new IllegalArgumentException("not an array: " + arrayClass);
 157 
 158         Class<?> componentType = arrayClass.getComponentType();
 159 
 160         int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
 161         int ascale = UNSAFE.arrayIndexScale(arrayClass);
 162         int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
 163 
 164         if (!componentType.isPrimitive()) {
 165             // the redundant componentType.isValue() check is there to
 166             // minimize the performance impact to non-value array.
 167             // It should be removed when Unsafe::isFlattenedArray is intrinsified.
 168             return componentType.isValue() && UNSAFE.isFlattenedArray(arrayClass)
 169                 ? new VarHandleObjects.ValueArray(aoffset, ashift, arrayClass)
 170                 : new VarHandleObjects.Array(aoffset, ashift, arrayClass);
 171         }
 172         else if (componentType == boolean.class) {
 173             return new VarHandleBooleans.Array(aoffset, ashift);
 174         }
 175         else if (componentType == byte.class) {
 176             return new VarHandleBytes.Array(aoffset, ashift);
 177         }
 178         else if (componentType == short.class) {
 179             return new VarHandleShorts.Array(aoffset, ashift);
 180         }
 181         else if (componentType == char.class) {
 182             return new VarHandleChars.Array(aoffset, ashift);
 183         }
 184         else if (componentType == int.class) {
 185             return new VarHandleInts.Array(aoffset, ashift);
 186         }
 187         else if (componentType == long.class) {
 188             return new VarHandleLongs.Array(aoffset, ashift);
 189         }
 190         else if (componentType == float.class) {
 191             return new VarHandleFloats.Array(aoffset, ashift);
 192         }
 193         else if (componentType == double.class) {
 194             return new VarHandleDoubles.Array(aoffset, ashift);
 195         }
 196         else {
 197             throw new UnsupportedOperationException();
 198         }
 199     }
 200 
 201     static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
 202                                          boolean be) {
 203         if (!viewArrayClass.isArray())
 204             throw new IllegalArgumentException("not an array: " + viewArrayClass);
 205 
 206         Class<?> viewComponentType = viewArrayClass.getComponentType();
 207 
 208         if (viewComponentType == long.class) {
 209             return new VarHandleByteArrayAsLongs.ArrayHandle(be);
 210         }
 211         else if (viewComponentType == int.class) {
 212             return new VarHandleByteArrayAsInts.ArrayHandle(be);
 213         }
 214         else if (viewComponentType == short.class) {
 215             return new VarHandleByteArrayAsShorts.ArrayHandle(be);
 216         }
 217         else if (viewComponentType == char.class) {
 218             return new VarHandleByteArrayAsChars.ArrayHandle(be);
 219         }
 220         else if (viewComponentType == double.class) {
 221             return new VarHandleByteArrayAsDoubles.ArrayHandle(be);
 222         }
 223         else if (viewComponentType == float.class) {
 224             return new VarHandleByteArrayAsFloats.ArrayHandle(be);
 225         }
 226 
 227         throw new UnsupportedOperationException();
 228     }
 229 
 230     static VarHandle makeByteBufferViewHandle(Class<?> viewArrayClass,
 231                                               boolean be) {
 232         if (!viewArrayClass.isArray())
 233             throw new IllegalArgumentException("not an array: " + viewArrayClass);
 234 
 235         Class<?> viewComponentType = viewArrayClass.getComponentType();
 236 
 237         if (viewComponentType == long.class) {
 238             return new VarHandleByteArrayAsLongs.ByteBufferHandle(be);
 239         }
 240         else if (viewComponentType == int.class) {
 241             return new VarHandleByteArrayAsInts.ByteBufferHandle(be);
 242         }
 243         else if (viewComponentType == short.class) {
 244             return new VarHandleByteArrayAsShorts.ByteBufferHandle(be);
 245         }
 246         else if (viewComponentType == char.class) {
 247             return new VarHandleByteArrayAsChars.ByteBufferHandle(be);
 248         }
 249         else if (viewComponentType == double.class) {
 250             return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be);
 251         }
 252         else if (viewComponentType == float.class) {
 253             return new VarHandleByteArrayAsFloats.ByteBufferHandle(be);
 254         }
 255 
 256         throw new UnsupportedOperationException();
 257     }
 258 
 259 //    /**
 260 //     * A helper program to generate the VarHandleGuards class with a set of
 261 //     * static guard methods each of which corresponds to a particular shape and
 262 //     * performs a type check of the symbolic type descriptor with the VarHandle
 263 //     * type descriptor before linking/invoking to the underlying operation as
 264 //     * characterized by the operation member name on the VarForm of the
 265 //     * VarHandle.
 266 //     * <p>
 267 //     * The generated class essentially encapsulates pre-compiled LambdaForms,
 268 //     * one for each method, for the most set of common method signatures.
 269 //     * This reduces static initialization costs, footprint costs, and circular
 270 //     * dependencies that may arise if a class is generated per LambdaForm.
 271 //     * <p>
 272 //     * A maximum of L*T*S methods will be generated where L is the number of
 273 //     * access modes kinds (or unique operation signatures) and T is the number
 274 //     * of variable types and S is the number of shapes (such as instance field,
 275 //     * static field, or array access).
 276 //     * If there are 4 unique operation signatures, 5 basic types (Object, int,
 277 //     * long, float, double), and 3 shapes then a maximum of 60 methods will be
 278 //     * generated.  However, the number is likely to be less since there
 279 //     * be duplicate signatures.
 280 //     * <p>
 281 //     * Each method is annotated with @LambdaForm.Compiled to inform the runtime
 282 //     * that such methods should be treated as if a method of a class that is the
 283 //     * result of compiling a LambdaForm.  Annotation of such methods is
 284 //     * important for correct evaluation of certain assertions and method return
 285 //     * type profiling in HotSpot.
 286 //     */
 287 //    public static class GuardMethodGenerator {
 288 //
 289 //        static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
 290 //
 291 //        static final String GUARD_METHOD_TEMPLATE =
 292 //                "@ForceInline\n" +
 293 //                "@LambdaForm.Compiled\n" +
 294 //                "final static <METHOD> throws Throwable {\n" +
 295 //                "    if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
 296 //                "        <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
 297 //                "    }\n" +
 298 //                "    else {\n" +
 299 //                "        MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
 300 //                "        <RETURN>mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
 301 //                "    }\n" +
 302 //                "}";
 303 //
 304 //        static final String GUARD_METHOD_TEMPLATE_V =
 305 //                "@ForceInline\n" +
 306 //                "@LambdaForm.Compiled\n" +
 307 //                "final static <METHOD> throws Throwable {\n" +
 308 //                "    if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
 309 //                "        MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
 310 //                "    }\n" +
 311 //                "    else if (handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodType) {\n" +
 312 //                "        MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
 313 //                "    }\n" +
 314 //                "    else {\n" +
 315 //                "        MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
 316 //                "        mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
 317 //                "    }\n" +
 318 //                "}";
 319 //
 320 //        // A template for deriving the operations
 321 //        // could be supported by annotating VarHandle directly with the
 322 //        // operation kind and shape
 323 //        interface VarHandleTemplate {
 324 //            Object get();
 325 //
 326 //            void set(Object value);
 327 //
 328 //            boolean compareAndSet(Object actualValue, Object expectedValue);
 329 //
 330 //            Object compareAndExchange(Object actualValue, Object expectedValue);
 331 //
 332 //            Object getAndUpdate(Object value);
 333 //        }
 334 //
 335 //        static class HandleType {
 336 //            final Class<?> receiver;
 337 //            final Class<?>[] intermediates;
 338 //            final Class<?> value;
 339 //
 340 //            HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
 341 //                this.receiver = receiver;
 342 //                this.intermediates = intermediates;
 343 //                this.value = value;
 344 //            }
 345 //        }
 346 //
 347 //        /**
 348 //         * @param args parameters
 349 //         */
 350 //        public static void main(String[] args) {
 351 //            System.out.println("package java.lang.invoke;");
 352 //            System.out.println();
 353 //            System.out.println("import jdk.internal.vm.annotation.ForceInline;");
 354 //            System.out.println();
 355 //            System.out.println("// This class is auto-generated by " +
 356 //                               GuardMethodGenerator.class.getName() +
 357 //                               ". Do not edit.");
 358 //            System.out.println("final class VarHandleGuards {");
 359 //
 360 //            System.out.println();
 361 //
 362 //            // Declare the stream of shapes
 363 //            Stream<HandleType> hts = Stream.of(
 364 //                    // Object->Object
 365 //                    new HandleType(Object.class, Object.class),
 366 //                    // Object->int
 367 //                    new HandleType(Object.class, int.class),
 368 //                    // Object->long
 369 //                    new HandleType(Object.class, long.class),
 370 //                    // Object->float
 371 //                    new HandleType(Object.class, float.class),
 372 //                    // Object->double
 373 //                    new HandleType(Object.class, double.class),
 374 //
 375 //                    // <static>->Object
 376 //                    new HandleType(null, Object.class),
 377 //                    // <static>->int
 378 //                    new HandleType(null, int.class),
 379 //                    // <static>->long
 380 //                    new HandleType(null, long.class),
 381 //                    // <static>->float
 382 //                    new HandleType(null, float.class),
 383 //                    // <static>->double
 384 //                    new HandleType(null, double.class),
 385 //
 386 //                    // Array[int]->Object
 387 //                    new HandleType(Object.class, Object.class, int.class),
 388 //                    // Array[int]->int
 389 //                    new HandleType(Object.class, int.class, int.class),
 390 //                    // Array[int]->long
 391 //                    new HandleType(Object.class, long.class, int.class),
 392 //                    // Array[int]->float
 393 //                    new HandleType(Object.class, float.class, int.class),
 394 //                    // Array[int]->double
 395 //                    new HandleType(Object.class, double.class, int.class),
 396 //
 397 //                    // Array[long]->int
 398 //                    new HandleType(Object.class, int.class, long.class),
 399 //                    // Array[long]->long
 400 //                    new HandleType(Object.class, long.class, long.class)
 401 //            );
 402 //
 403 //            hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
 404 //                    map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
 405 //                    distinct().
 406 //                    map(mt -> generateMethod(mt)).
 407 //                    forEach(s -> {
 408 //                        System.out.println(s);
 409 //                        System.out.println();
 410 //                    });
 411 //
 412 //            System.out.println("}");
 413 //        }
 414 //
 415 //        static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
 416 //            Class<?> returnType = m.getReturnType() == Object.class
 417 //                                  ? value : m.getReturnType();
 418 //
 419 //            List<Class<?>> params = new ArrayList<>();
 420 //            if (receiver != null)
 421 //                params.add(receiver);
 422 //            for (int i = 0; i < intermediates.length; i++) {
 423 //                params.add(intermediates[i]);
 424 //            }
 425 //            for (Parameter p : m.getParameters()) {
 426 //                params.add(value);
 427 //            }
 428 //            return MethodType.methodType(returnType, params);
 429 //        }
 430 //
 431 //        static String generateMethod(MethodType mt) {
 432 //            Class<?> returnType = mt.returnType();
 433 //
 434 //            LinkedHashMap<String, Class<?>> params = new LinkedHashMap<>();
 435 //            params.put("handle", VarHandle.class);
 436 //            for (int i = 0; i < mt.parameterCount(); i++) {
 437 //                params.put("arg" + i, mt.parameterType(i));
 438 //            }
 439 //            params.put("ad", VarHandle.AccessDescriptor.class);
 440 //
 441 //            // Generate method signature line
 442 //            String RETURN = className(returnType);
 443 //            String NAME = "guard";
 444 //            String SIGNATURE = getSignature(mt);
 445 //            String PARAMS = params.entrySet().stream().
 446 //                    map(e -> className(e.getValue()) + " " + e.getKey()).
 447 //                    collect(joining(", "));
 448 //            String METHOD = GUARD_METHOD_SIG_TEMPLATE.
 449 //                    replace("<RETURN>", RETURN).
 450 //                    replace("<NAME>", NAME).
 451 //                    replace("<SIGNATURE>", SIGNATURE).
 452 //                    replace("<PARAMS>", PARAMS);
 453 //
 454 //            // Generate method
 455 //            params.remove("ad");
 456 //
 457 //            List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
 458 //                    collect(toList());
 459 //            LINK_TO_STATIC_ARGS.add("handle.vform.getMemberName(ad.mode)");
 460 //            List<String> LINK_TO_STATIC_ARGS_V = params.keySet().stream().
 461 //                    collect(toList());
 462 //            LINK_TO_STATIC_ARGS_V.add("handle.vform.getMemberName_V(ad.mode)");
 463 //
 464 //            List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
 465 //                    collect(toList());
 466 //
 467 //            RETURN = returnType == void.class
 468 //                     ? ""
 469 //                     : returnType == Object.class
 470 //                       ? "return "
 471 //                       : "return (" + returnType.getName() + ") ";
 472 //
 473 //            String RESULT_ERASED = returnType == void.class
 474 //                                   ? ""
 475 //                                   : returnType != Object.class
 476 //                                     ? "return (" + returnType.getName() + ") "
 477 //                                     : "Object r = ";
 478 //
 479 //            String RETURN_ERASED = returnType != Object.class
 480 //                                   ? ""
 481 //                                   : " return ad.returnType.cast(r);";
 482 //
 483 //            String template = returnType == void.class
 484 //                              ? GUARD_METHOD_TEMPLATE_V
 485 //                              : GUARD_METHOD_TEMPLATE;
 486 //            return template.
 487 //                    replace("<METHOD>", METHOD).
 488 //                    replace("<NAME>", NAME).
 489 //                    replaceAll("<RETURN>", RETURN).
 490 //                    replace("<RESULT_ERASED>", RESULT_ERASED).
 491 //                    replace("<RETURN_ERASED>", RETURN_ERASED).
 492 //                    replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
 493 //                            collect(joining(", "))).
 494 //                    replaceAll("<LINK_TO_STATIC_ARGS_V>", LINK_TO_STATIC_ARGS_V.stream().
 495 //                            collect(joining(", "))).
 496 //                    replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
 497 //                            collect(joining(", ")))
 498 //                    ;
 499 //        }
 500 //
 501 //        static String className(Class<?> c) {
 502 //            String n = c.getName();
 503 //            if (n.startsWith("java.lang.")) {
 504 //                n = n.replace("java.lang.", "");
 505 //                if (n.startsWith("invoke.")) {
 506 //                    n = n.replace("invoke.", "");
 507 //                }
 508 //            }
 509 //            return n.replace('$', '.');
 510 //        }
 511 //
 512 //        static String getSignature(MethodType m) {
 513 //            StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
 514 //
 515 //            for (int i = 0; i < m.parameterCount(); i++) {
 516 //                Class<?> pt = m.parameterType(i);
 517 //                sb.append(getCharType(pt));
 518 //            }
 519 //
 520 //            sb.append('_').append(getCharType(m.returnType()));
 521 //
 522 //            return sb.toString();
 523 //        }
 524 //
 525 //        static char getCharType(Class<?> pt) {
 526 //            if (pt == void.class) {
 527 //                return 'V';
 528 //            }
 529 //            else if (!pt.isPrimitive()) {
 530 //                return 'L';
 531 //            }
 532 //            else if (pt == boolean.class) {
 533 //                return 'Z';
 534 //            }
 535 //            else if (pt == int.class) {
 536 //                return 'I';
 537 //            }
 538 //            else if (pt == long.class) {
 539 //                return 'J';
 540 //            }
 541 //            else if (pt == float.class) {
 542 //                return 'F';
 543 //            }
 544 //            else if (pt == double.class) {
 545 //                return 'D';
 546 //            }
 547 //            else {
 548 //                throw new IllegalStateException(pt.getName());
 549 //            }
 550 //        }
 551 //    }
 552 }