Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (c) 2001, 2003, 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 "jni.h"
     27 #include "jvm.h"
     28 
     29 #include "JNIHelp.h"
     30 
     31 #define NATIVE_METHOD(className, functionName, signature) \
     32 { #functionName, signature, (void*)(className ## _ ## functionName) }
     33 
     34 static jclass noSuchMethodErrCl;
     35 
     36 static void ObjectStreamClass_initNative(JNIEnv *env)
     37 {
     38     jclass cl = (*env)->FindClass(env, "java/lang/NoSuchMethodError");
     39     if (cl == NULL) {           /* exception thrown */
     40         return;
     41     }
     42     noSuchMethodErrCl = (*env)->NewGlobalRef(env, cl);
     43 }
     44 
     45 /*
     46  * Class:     java_io_ObjectStreamClass
     47  * Method:    hasStaticInitializer
     48  * Signature: (Ljava/lang/Class;Z)Z
     49  *
     50  * Returns true if the given class defines a <clinit>()V method; returns false
     51  * otherwise.
     52  */
     53 JNIEXPORT jboolean JNICALL
     54 ObjectStreamClass_hasStaticInitializer(JNIEnv *env, jclass this,
     55                                        jclass clazz,
     56                                        jboolean checkSuperclass)
     57 {
     58     jclass superCl = NULL;
     59     jmethodID superClinitId = NULL;
     60     jmethodID clinitId =
     61         (*env)->GetStaticMethodID(env, clazz, "<clinit>", "()V");
     62     if (clinitId == NULL) {     /* error thrown */
     63         jthrowable th = (*env)->ExceptionOccurred(env);
     64         (*env)->ExceptionClear(env);    /* normal return */
     65         if (!(*env)->IsInstanceOf(env, th, noSuchMethodErrCl)) {
     66             (*env)->Throw(env, th);
     67         }
     68         return JNI_FALSE;
     69     }
     70 
     71     // Android-changed, if checkSuperclass == true, remove check for
     72     // superclass clinitId != child clinitId.
     73     // We're returning true to enable deserializing classes without explicit serialVersionID
     74     // that would fail in this check (b/29064453).
     75     if (checkSuperclass == JNI_FALSE) {
     76         return JNI_TRUE;
     77     }
     78 
     79     /*
     80      * Check superclass for static initializer as well--if the same method ID
     81      * is returned, then the static initializer is from a superclass.
     82      * Empirically, this step appears to be unnecessary in 1.4; however, the
     83      * JNI spec makes no guarantee that GetStaticMethodID will not return the
     84      * ID for a superclass initializer.
     85      */
     86     if ((superCl = (*env)->GetSuperclass(env, clazz)) == NULL) {
     87         return JNI_TRUE;
     88     }
     89     superClinitId =
     90         (*env)->GetStaticMethodID(env, superCl, "<clinit>", "()V");
     91     if (superClinitId == NULL) {        /* error thrown */
     92         jthrowable th = (*env)->ExceptionOccurred(env);
     93         (*env)->ExceptionClear(env);    /* normal return */
     94         if (!(*env)->IsInstanceOf(env, th, noSuchMethodErrCl)) {
     95             (*env)->Throw(env, th);
     96         }
     97         return JNI_TRUE;
     98     }
     99 
    100     return (clinitId != superClinitId);
    101 }
    102 
    103 static JNINativeMethod gMethods[] = {
    104   NATIVE_METHOD(ObjectStreamClass, hasStaticInitializer, "(Ljava/lang/Class;Z)Z"),
    105 };
    106 
    107 void register_java_io_ObjectStreamClass(JNIEnv* env) {
    108   jniRegisterNativeMethods(env, "java/io/ObjectStreamClass", gMethods, NELEM(gMethods));
    109   ObjectStreamClass_initNative(env);
    110 }
    111