1 /* 2 * Copyright (c) 1996, 2020, 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 <stdlib.h> 27 #include <assert.h> 28 29 #include "jni.h" 30 #include "jni_util.h" 31 #include "jlong.h" 32 #include "jvm.h" 33 #include "check_classname.h" 34 #include "java_lang_ClassLoader.h" 35 #include <string.h> 36 37 static JNINativeMethod methods[] = { 38 {"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives} 39 }; 40 41 JNIEXPORT void JNICALL 42 Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls) 43 { 44 (*env)->RegisterNatives(env, cls, methods, 45 sizeof(methods)/sizeof(JNINativeMethod)); 46 } 47 48 /* Convert java string to UTF char*. Use local buffer if possible, 49 otherwise malloc new memory. Returns null IFF malloc failed. */ 50 static char* 51 getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize) 52 { 53 char* utfStr = NULL; 54 55 int len = (*env)->GetStringUTFLength(env, str); 56 int unicode_len = (*env)->GetStringLength(env, str); 57 if (len >= bufSize) { 58 utfStr = malloc(len + 1); 59 if (utfStr == NULL) { 60 JNU_ThrowOutOfMemoryError(env, NULL); 61 return NULL; 62 } 63 } else { 64 utfStr = localBuf; 65 } 66 (*env)->GetStringUTFRegion(env, str, 0, unicode_len, utfStr); 67 68 return utfStr; 69 } 70 71 JNIEXPORT jclass JNICALL 72 Java_java_lang_ClassLoader_defineClass1(JNIEnv *env, 73 jclass cls, 74 jobject loader, 75 jstring name, 76 jbyteArray data, 77 jint offset, 78 jint length, 79 jobject pd, 80 jstring source) 81 { 82 jbyte *body; 83 char *utfName; 84 jclass result = 0; 85 char buf[128]; 86 char* utfSource; 87 char sourceBuf[1024]; 88 89 if (data == NULL) { 90 JNU_ThrowNullPointerException(env, 0); 91 return 0; 92 } 93 94 /* Work around 4153825. malloc crashes on Solaris when passed a 95 * negative size. 96 */ 97 if (length < 0) { 98 JNU_ThrowArrayIndexOutOfBoundsException(env, 0); 99 return 0; 100 } 101 102 body = (jbyte *)malloc(length); 103 104 if (body == 0) { 105 JNU_ThrowOutOfMemoryError(env, 0); 106 return 0; 107 } 108 109 (*env)->GetByteArrayRegion(env, data, offset, length, body); 110 111 if ((*env)->ExceptionOccurred(env)) 112 goto free_body; 113 114 if (name != NULL) { 115 utfName = getUTF(env, name, buf, sizeof(buf)); 116 if (utfName == NULL) { 117 goto free_body; 118 } 119 fixClassname(utfName); 120 } else { 121 utfName = NULL; 122 } 123 124 if (source != NULL) { 125 utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf)); 126 if (utfSource == NULL) { 127 goto free_utfName; 128 } 129 } else { 130 utfSource = NULL; 131 } 132 result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource); 133 134 if (utfSource && utfSource != sourceBuf) 135 free(utfSource); 136 137 free_utfName: 138 if (utfName && utfName != buf) 139 free(utfName); 140 141 free_body: 142 free(body); 143 return result; 144 } 145 146 JNIEXPORT jclass JNICALL 147 Java_java_lang_ClassLoader_defineClass2(JNIEnv *env, 148 jclass cls, 149 jobject loader, 150 jstring name, 151 jobject data, 152 jint offset, 153 jint length, 154 jobject pd, 155 jstring source) 156 { 157 jbyte *body; 158 char *utfName; 159 jclass result = 0; 160 char buf[128]; 161 char* utfSource; 162 char sourceBuf[1024]; 163 164 assert(data != NULL); // caller fails if data is null. 165 assert(length >= 0); // caller passes ByteBuffer.remaining() for length, so never neg. 166 // caller passes ByteBuffer.position() for offset, and capacity() >= position() + remaining() 167 assert((*env)->GetDirectBufferCapacity(env, data) >= (offset + length)); 168 169 body = (*env)->GetDirectBufferAddress(env, data); 170 171 if (body == 0) { 172 JNU_ThrowNullPointerException(env, 0); 173 return 0; 174 } 175 176 body += offset; 177 178 if (name != NULL) { 179 utfName = getUTF(env, name, buf, sizeof(buf)); 180 if (utfName == NULL) { 181 JNU_ThrowOutOfMemoryError(env, NULL); 182 return result; 183 } 184 fixClassname(utfName); 185 } else { 186 utfName = NULL; 187 } 188 189 if (source != NULL) { 190 utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf)); 191 if (utfSource == NULL) { 192 JNU_ThrowOutOfMemoryError(env, NULL); 193 goto free_utfName; 194 } 195 } else { 196 utfSource = NULL; 197 } 198 result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource); 199 200 if (utfSource && utfSource != sourceBuf) 201 free(utfSource); 202 203 free_utfName: 204 if (utfName && utfName != buf) 205 free(utfName); 206 207 return result; 208 } 209 210 /* 211 * Returns NULL if class not found. 212 */ 213 JNIEXPORT jclass JNICALL 214 Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader, 215 jstring classname) 216 { 217 char *clname; 218 jclass cls = 0; 219 char buf[128]; 220 221 if (classname == NULL) { 222 return 0; 223 } 224 225 clname = getUTF(env, classname, buf, sizeof(buf)); 226 if (clname == NULL) { 227 JNU_ThrowOutOfMemoryError(env, NULL); 228 return NULL; 229 } 230 fixClassname(clname); 231 232 if (!verifyClassname(clname, JNI_TRUE)) { /* expects slashed name */ 233 goto done; 234 } 235 236 cls = JVM_FindClassFromBootLoader(env, clname); 237 238 done: 239 if (clname != buf) { 240 free(clname); 241 } 242 243 return cls; 244 } 245 246 JNIEXPORT jclass JNICALL 247 Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader, 248 jstring name) 249 { 250 if (name == NULL) { 251 return 0; 252 } else { 253 return JVM_FindLoadedClass(env, loader, name); 254 } 255 }