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 <nativehelper/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