jdk
1/*
2* Copyright (c) 1996, 2022, 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 <assert.h>27#include <stdlib.h>28#include <string.h>29
30#include "check_classname.h"31#include "java_lang_ClassLoader.h"32#include "jlong.h"33#include "jni.h"34#include "jni_util.h"35#include "jvm.h"36
37static JNINativeMethod methods[] = {38{"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives}39};40
41JNIEXPORT void JNICALL42Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls)43{
44(*env)->RegisterNatives(env, cls, methods,45sizeof(methods)/sizeof(JNINativeMethod));46}
47
48/* Convert java string to UTF char*. Use local buffer if possible,
49otherwise malloc new memory. Returns null IFF malloc failed. */
50static char*51getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize)52{
53char* utfStr = NULL;54
55int len = (*env)->GetStringUTFLength(env, str);56int unicode_len = (*env)->GetStringLength(env, str);57if (len >= bufSize) {58utfStr = malloc(len + 1);59if (utfStr == NULL) {60JNU_ThrowOutOfMemoryError(env, NULL);61return NULL;62}63} else {64utfStr = localBuf;65}66(*env)->GetStringUTFRegion(env, str, 0, unicode_len, utfStr);67
68return utfStr;69}
70
71JNIEXPORT jclass JNICALL
72Java_java_lang_ClassLoader_defineClass1(JNIEnv *env,73jclass cls,74jobject loader,75jstring name,76jbyteArray data,77jint offset,78jint length,79jobject pd,80jstring source)81{
82jbyte *body;83char *utfName;84jclass result = 0;85char buf[128];86char* utfSource;87char sourceBuf[1024];88
89if (data == NULL) {90JNU_ThrowNullPointerException(env, 0);91return NULL;92}93
94/* Work around 4153825. malloc crashes on Solaris when passed a95* negative size.
96*/
97if (length < 0) {98JNU_ThrowArrayIndexOutOfBoundsException(env, 0);99return NULL;100}101
102// On AIX malloc(0) returns NULL which looks like an out-of-memory103// condition; so adjust it to malloc(1)104#ifdef _AIX105body = (jbyte *)malloc(length == 0 ? 1 : length);106#else107body = (jbyte *)malloc(length);108#endif109
110if (body == NULL) {111JNU_ThrowOutOfMemoryError(env, 0);112return NULL;113}114
115(*env)->GetByteArrayRegion(env, data, offset, length, body);116
117if ((*env)->ExceptionOccurred(env)) {118goto free_body;119}120
121if (name != NULL) {122utfName = getUTF(env, name, buf, sizeof(buf));123if (utfName == NULL) {124goto free_body;125}126fixClassname(utfName);127} else {128utfName = NULL;129}130
131if (source != NULL) {132utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf));133if (utfSource == NULL) {134goto free_utfName;135}136} else {137utfSource = NULL;138}139result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);140
141if (utfSource && utfSource != sourceBuf)142free(utfSource);143
144free_utfName:145if (utfName && utfName != buf)146free(utfName);147
148free_body:149free(body);150return result;151}
152
153JNIEXPORT jclass JNICALL
154Java_java_lang_ClassLoader_defineClass2(JNIEnv *env,155jclass cls,156jobject loader,157jstring name,158jobject data,159jint offset,160jint length,161jobject pd,162jstring source)163{
164jbyte *body;165char *utfName;166jclass result = 0;167char buf[128];168char* utfSource;169char sourceBuf[1024];170
171assert(data != NULL); // caller fails if data is null.172assert(length >= 0); // caller passes ByteBuffer.remaining() for length, so never neg.173// caller passes ByteBuffer.position() for offset, and capacity() >= position() + remaining()174assert((*env)->GetDirectBufferCapacity(env, data) >= (offset + length));175
176body = (*env)->GetDirectBufferAddress(env, data);177
178if (body == NULL) {179JNU_ThrowNullPointerException(env, 0);180return NULL;181}182
183body += offset;184
185if (name != NULL) {186utfName = getUTF(env, name, buf, sizeof(buf));187if (utfName == NULL) {188return result;189}190fixClassname(utfName);191} else {192utfName = NULL;193}194
195if (source != NULL) {196utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf));197if (utfSource == NULL) {198goto free_utfName;199}200} else {201utfSource = NULL;202}203result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);204
205if (utfSource && utfSource != sourceBuf)206free(utfSource);207
208free_utfName:209if (utfName && utfName != buf)210free(utfName);211
212return result;213}
214
215JNIEXPORT jclass JNICALL
216Java_java_lang_ClassLoader_defineClass0(JNIEnv *env,217jclass cls,218jobject loader,219jclass lookup,220jstring name,221jbyteArray data,222jint offset,223jint length,224jobject pd,225jboolean initialize,226jint flags,227jobject classData)228{
229jbyte *body;230char *utfName;231jclass result = 0;232char buf[128];233
234if (data == NULL) {235JNU_ThrowNullPointerException(env, 0);236return NULL;237}238
239/* Work around 4153825. malloc crashes on Solaris when passed a240* negative size.
241*/
242if (length < 0) {243JNU_ThrowArrayIndexOutOfBoundsException(env, 0);244return NULL;245}246
247// On AIX malloc(0) returns NULL which looks like an out-of-memory248// condition; so adjust it to malloc(1)249#ifdef _AIX250body = (jbyte *)malloc(length == 0 ? 1 : length);251#else252body = (jbyte *)malloc(length);253#endif254
255if (body == NULL) {256JNU_ThrowOutOfMemoryError(env, 0);257return NULL;258}259
260(*env)->GetByteArrayRegion(env, data, offset, length, body);261
262if ((*env)->ExceptionOccurred(env))263goto free_body;264
265if (name != NULL) {266utfName = getUTF(env, name, buf, sizeof(buf));267if (utfName == NULL) {268goto free_body;269}270fixClassname(utfName);271} else {272utfName = NULL;273}274
275result = JVM_LookupDefineClass(env, lookup, utfName, body, length, pd, initialize, flags, classData);276
277if (utfName && utfName != buf)278free(utfName);279
280free_body:281free(body);282return result;283}
284
285/*
286* Returns NULL if class not found.
287*/
288JNIEXPORT jclass JNICALL
289Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jclass dummy,290jstring classname)291{
292char *clname;293jclass cls = 0;294char buf[128];295
296if (classname == NULL) {297return NULL;298}299
300clname = getUTF(env, classname, buf, sizeof(buf));301if (clname == NULL) {302return NULL;303}304fixClassname(clname);305
306if (!verifyClassname(clname, JNI_TRUE)) { /* expects slashed name */307goto done;308}309
310cls = JVM_FindClassFromBootLoader(env, clname);311
312done:313if (clname != buf) {314free(clname);315}316
317return cls;318}
319
320JNIEXPORT jclass JNICALL
321Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader,322jstring name)323{
324if (name == NULL) {325return NULL;326} else {327return JVM_FindLoadedClass(env, loader, name);328}329}
330