Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 1998, 2005, 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 #include "ArrayTypeImpl.h"
     27 #include "util.h"
     28 #include "inStream.h"
     29 #include "outStream.h"
     30 
     31 /*
     32  * Determine the component class by looking thru all classes for
     33  * one that has the signature of the component and the same class loadeer
     34  * as the array.  See JVM spec 5.3.3:
     35  *     If the component type is a reference type, C is marked as having
     36  *     been defined by the defining class loader of the component type.
     37  */
     38 static jdwpError
     39 getComponentClass(JNIEnv *env, jclass arrayClass, char *componentSignature,
     40                 jclass *componentClassPtr)
     41 {
     42     jobject arrayClassLoader;
     43     jclass *classes;
     44     jint count;
     45     jclass componentClass = NULL;
     46     jdwpError serror;
     47     jvmtiError error;
     48 
     49     serror = JDWP_ERROR(NONE);
     50 
     51     error = classLoader(arrayClass, &arrayClassLoader);
     52     if (error != JVMTI_ERROR_NONE) {
     53         return map2jdwpError(error);
     54     }
     55 
     56     error = allLoadedClasses(&classes, &count);
     57     if (error != JVMTI_ERROR_NONE) {
     58         serror = map2jdwpError(error);
     59     } else {
     60         int i;
     61         for (i = 0; (i < count) && (componentClass == NULL); i++) {
     62             char *signature = NULL;
     63             jclass clazz = classes[i];
     64             jboolean match;
     65             jvmtiError error;
     66 
     67             /* signature must match */
     68             error = classSignature(clazz, &signature, NULL);
     69             if (error != JVMTI_ERROR_NONE) {
     70                 serror = map2jdwpError(error);
     71                 break;
     72             }
     73             match = strcmp(signature, componentSignature) == 0;
     74             jvmtiDeallocate(signature);
     75 
     76             /* if signature matches, get class loader to check if
     77              * it matches
     78              */
     79             if (match) {
     80                 jobject loader;
     81                 error = classLoader(clazz, &loader);
     82                 if (error != JVMTI_ERROR_NONE) {
     83                     return map2jdwpError(error);
     84                 }
     85                 match = isSameObject(env, loader, arrayClassLoader);
     86             }
     87 
     88             if (match) {
     89                 componentClass = clazz;
     90             }
     91         }
     92         jvmtiDeallocate(classes);
     93 
     94         *componentClassPtr = componentClass;
     95     }
     96 
     97     if (serror == JDWP_ERROR(NONE) && componentClass == NULL) {
     98         /* per JVM spec, component class is always loaded
     99          * before array class, so this should never occur.
    100          */
    101         serror = JDWP_ERROR(NOT_FOUND);
    102     }
    103 
    104     return serror;
    105 }
    106 
    107 static void
    108 writeNewObjectArray(JNIEnv *env, PacketOutputStream *out,
    109                  jclass arrayClass, jint size, char *componentSignature)
    110 {
    111 
    112     WITH_LOCAL_REFS(env, 1) {
    113 
    114         jarray array;
    115         jclass componentClass;
    116         jdwpError serror;
    117 
    118         serror = getComponentClass(env, arrayClass,
    119                                        componentSignature, &componentClass);
    120         if (serror != JDWP_ERROR(NONE)) {
    121             outStream_setError(out, serror);
    122         } else {
    123 
    124             array = JNI_FUNC_PTR(env,NewObjectArray)(env, size, componentClass, 0);
    125             if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    126                 JNI_FUNC_PTR(env,ExceptionClear)(env);
    127                 array = NULL;
    128             }
    129 
    130             if (array == NULL) {
    131                 outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    132             } else {
    133                 (void)outStream_writeByte(out, specificTypeKey(env, array));
    134                 (void)outStream_writeObjectRef(env, out, array);
    135             }
    136 
    137         }
    138 
    139     } END_WITH_LOCAL_REFS(env);
    140 }
    141 
    142 static void
    143 writeNewPrimitiveArray(JNIEnv *env, PacketOutputStream *out,
    144                        jclass arrayClass, jint size, char *componentSignature)
    145 {
    146 
    147     WITH_LOCAL_REFS(env, 1) {
    148 
    149         jarray array = NULL;
    150 
    151         switch (componentSignature[0]) {
    152             case JDWP_TAG(BYTE):
    153                 array = JNI_FUNC_PTR(env,NewByteArray)(env, size);
    154                 break;
    155 
    156             case JDWP_TAG(CHAR):
    157                 array = JNI_FUNC_PTR(env,NewCharArray)(env, size);
    158                 break;
    159 
    160             case JDWP_TAG(FLOAT):
    161                 array = JNI_FUNC_PTR(env,NewFloatArray)(env, size);
    162                 break;
    163 
    164             case JDWP_TAG(DOUBLE):
    165                 array = JNI_FUNC_PTR(env,NewDoubleArray)(env, size);
    166                 break;
    167 
    168             case JDWP_TAG(INT):
    169                 array = JNI_FUNC_PTR(env,NewIntArray)(env, size);
    170                 break;
    171 
    172             case JDWP_TAG(LONG):
    173                 array = JNI_FUNC_PTR(env,NewLongArray)(env, size);
    174                 break;
    175 
    176             case JDWP_TAG(SHORT):
    177                 array = JNI_FUNC_PTR(env,NewShortArray)(env, size);
    178                 break;
    179 
    180             case JDWP_TAG(BOOLEAN):
    181                 array = JNI_FUNC_PTR(env,NewBooleanArray)(env, size);
    182                 break;
    183 
    184             default:
    185                 outStream_setError(out, JDWP_ERROR(TYPE_MISMATCH));
    186                 break;
    187         }
    188 
    189         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    190             JNI_FUNC_PTR(env,ExceptionClear)(env);
    191             array = NULL;
    192         }
    193 
    194         if (array == NULL) {
    195             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    196         } else {
    197             (void)outStream_writeByte(out, specificTypeKey(env, array));
    198             (void)outStream_writeObjectRef(env, out, array);
    199         }
    200 
    201     } END_WITH_LOCAL_REFS(env);
    202 }
    203 
    204 static jboolean
    205 newInstance(PacketInputStream *in, PacketOutputStream *out)
    206 {
    207     JNIEnv *env;
    208     char *signature = NULL;
    209     char *componentSignature;
    210     jclass arrayClass;
    211     jint size;
    212     jvmtiError error;
    213 
    214     env = getEnv();
    215 
    216     arrayClass = inStream_readClassRef(env, in);
    217     if (inStream_error(in)) {
    218         return JNI_TRUE;
    219     }
    220     size = inStream_readInt(in);
    221     if (inStream_error(in)) {
    222         return JNI_TRUE;
    223     }
    224 
    225     error = classSignature(arrayClass, &signature, NULL);
    226     if ( error != JVMTI_ERROR_NONE ) {
    227         outStream_setError(out, map2jdwpError(error));
    228         return JNI_FALSE;
    229     }
    230     componentSignature = &signature[1];
    231 
    232     if ((componentSignature[0] == JDWP_TAG(OBJECT)) ||
    233         (componentSignature[0] == JDWP_TAG(ARRAY))) {
    234         writeNewObjectArray(env, out, arrayClass, size, componentSignature);
    235     } else {
    236         writeNewPrimitiveArray(env, out, arrayClass, size, componentSignature);
    237     }
    238 
    239     jvmtiDeallocate(signature);
    240     return JNI_TRUE;
    241 }
    242 
    243 void *ArrayType_Cmds[] = { (void *)0x1
    244                           ,(void *)newInstance};
    245