Path: blob/master/src/java.base/share/native/libjava/ClassLoader.c
41149 views
/*1* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdlib.h>26#include <assert.h>2728#include "jni.h"29#include "jni_util.h"30#include "jlong.h"31#include "jvm.h"32#include "check_classname.h"33#include "java_lang_ClassLoader.h"34#include <string.h>3536static JNINativeMethod methods[] = {37{"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives}38};3940JNIEXPORT void JNICALL41Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls)42{43(*env)->RegisterNatives(env, cls, methods,44sizeof(methods)/sizeof(JNINativeMethod));45}4647/* Convert java string to UTF char*. Use local buffer if possible,48otherwise malloc new memory. Returns null IFF malloc failed. */49static char*50getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize)51{52char* utfStr = NULL;5354int len = (*env)->GetStringUTFLength(env, str);55int unicode_len = (*env)->GetStringLength(env, str);56if (len >= bufSize) {57utfStr = malloc(len + 1);58if (utfStr == NULL) {59JNU_ThrowOutOfMemoryError(env, NULL);60return NULL;61}62} else {63utfStr = localBuf;64}65(*env)->GetStringUTFRegion(env, str, 0, unicode_len, utfStr);6667return utfStr;68}6970JNIEXPORT jclass JNICALL71Java_java_lang_ClassLoader_defineClass1(JNIEnv *env,72jclass cls,73jobject loader,74jstring name,75jbyteArray data,76jint offset,77jint length,78jobject pd,79jstring source)80{81jbyte *body;82char *utfName;83jclass result = 0;84char buf[128];85char* utfSource;86char sourceBuf[1024];8788if (data == NULL) {89JNU_ThrowNullPointerException(env, 0);90return 0;91}9293/* Work around 4153825. malloc crashes on Solaris when passed a94* negative size.95*/96if (length < 0) {97JNU_ThrowArrayIndexOutOfBoundsException(env, 0);98return 0;99}100101body = (jbyte *)malloc(length);102103if (body == 0) {104JNU_ThrowOutOfMemoryError(env, 0);105return 0;106}107108(*env)->GetByteArrayRegion(env, data, offset, length, body);109110if ((*env)->ExceptionOccurred(env))111goto free_body;112113if (name != NULL) {114utfName = getUTF(env, name, buf, sizeof(buf));115if (utfName == NULL) {116goto free_body;117}118fixClassname(utfName);119} else {120utfName = NULL;121}122123if (source != NULL) {124utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf));125if (utfSource == NULL) {126goto free_utfName;127}128} else {129utfSource = NULL;130}131result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);132133if (utfSource && utfSource != sourceBuf)134free(utfSource);135136free_utfName:137if (utfName && utfName != buf)138free(utfName);139140free_body:141free(body);142return result;143}144145JNIEXPORT jclass JNICALL146Java_java_lang_ClassLoader_defineClass2(JNIEnv *env,147jclass cls,148jobject loader,149jstring name,150jobject data,151jint offset,152jint length,153jobject pd,154jstring source)155{156jbyte *body;157char *utfName;158jclass result = 0;159char buf[128];160char* utfSource;161char sourceBuf[1024];162163assert(data != NULL); // caller fails if data is null.164assert(length >= 0); // caller passes ByteBuffer.remaining() for length, so never neg.165// caller passes ByteBuffer.position() for offset, and capacity() >= position() + remaining()166assert((*env)->GetDirectBufferCapacity(env, data) >= (offset + length));167168body = (*env)->GetDirectBufferAddress(env, data);169170if (body == 0) {171JNU_ThrowNullPointerException(env, 0);172return 0;173}174175body += offset;176177if (name != NULL) {178utfName = getUTF(env, name, buf, sizeof(buf));179if (utfName == NULL) {180JNU_ThrowOutOfMemoryError(env, NULL);181return result;182}183fixClassname(utfName);184} else {185utfName = NULL;186}187188if (source != NULL) {189utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf));190if (utfSource == NULL) {191JNU_ThrowOutOfMemoryError(env, NULL);192goto free_utfName;193}194} else {195utfSource = NULL;196}197result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);198199if (utfSource && utfSource != sourceBuf)200free(utfSource);201202free_utfName:203if (utfName && utfName != buf)204free(utfName);205206return result;207}208209JNIEXPORT jclass JNICALL210Java_java_lang_ClassLoader_defineClass0(JNIEnv *env,211jclass cls,212jobject loader,213jclass lookup,214jstring name,215jbyteArray data,216jint offset,217jint length,218jobject pd,219jboolean initialize,220jint flags,221jobject classData)222{223jbyte *body;224char *utfName;225jclass result = 0;226char buf[128];227228if (data == NULL) {229JNU_ThrowNullPointerException(env, 0);230return 0;231}232233/* Work around 4153825. malloc crashes on Solaris when passed a234* negative size.235*/236if (length < 0) {237JNU_ThrowArrayIndexOutOfBoundsException(env, 0);238return 0;239}240241body = (jbyte *)malloc(length);242if (body == 0) {243JNU_ThrowOutOfMemoryError(env, 0);244return 0;245}246247(*env)->GetByteArrayRegion(env, data, offset, length, body);248249if ((*env)->ExceptionOccurred(env))250goto free_body;251252if (name != NULL) {253utfName = getUTF(env, name, buf, sizeof(buf));254if (utfName == NULL) {255goto free_body;256}257fixClassname(utfName);258} else {259utfName = NULL;260}261262result = JVM_LookupDefineClass(env, lookup, utfName, body, length, pd, initialize, flags, classData);263264if (utfName && utfName != buf)265free(utfName);266267free_body:268free(body);269return result;270}271272/*273* Returns NULL if class not found.274*/275JNIEXPORT jclass JNICALL276Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jclass dummy,277jstring classname)278{279char *clname;280jclass cls = 0;281char buf[128];282283if (classname == NULL) {284return 0;285}286287clname = getUTF(env, classname, buf, sizeof(buf));288if (clname == NULL) {289JNU_ThrowOutOfMemoryError(env, NULL);290return NULL;291}292fixClassname(clname);293294if (!verifyClassname(clname, JNI_TRUE)) { /* expects slashed name */295goto done;296}297298cls = JVM_FindClassFromBootLoader(env, clname);299300done:301if (clname != buf) {302free(clname);303}304305return cls;306}307308JNIEXPORT jclass JNICALL309Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader,310jstring name)311{312if (name == NULL) {313return 0;314} else {315return JVM_FindLoadedClass(env, loader, name);316}317}318319320