constructor.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 336 行
C
336 行
/* * @(#)Constructor.c 1.28 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/interpreter.h"#include "javavm/include/directmem.h"#include "javavm/include/indirectmem.h"#include "javavm/include/utils.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/reflect.h"#include "javavm/export/jvm.h"#ifdef CVM_REFLECT#include "generated/offsets/java_lang_Class.h"#include "generated/offsets/java_lang_reflect_AccessibleObject.h"#include "generated/offsets/java_lang_reflect_Constructor.h"#endif /* CVM_REFLECT */#ifdef CVM_REFLECT/* * Implementation essentially copied from Method.c and modified so it * throws Constructor's internal exceptions instead of Method's. See * Method.c for more documentation. */static CNIResultCodeCVMinvokeConstructor(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* NOTE that we are gc-UNSAFE when we enter and exit this method. This is very important. If the GC-safety policy for CVM native methods changes, much of this code will need to be run in an CVMD_gcUnsafeExec block. */ CVMFrame* frame; CVMObject* methodObject; CVMObject* obj; CVMMethodBlock* declaredMb; CVMObject* declaredClass; /* * read the java lang Class member variable classBlockPointer * into declaredCbAddr * therefore change the type to CVMAddr which is 4 byte on * 32 bit platforms and 8 byte on 64 bit platforms */ CVMAddr declaredCbAddr; CVMClassBlock* declaredCb; CVMArrayOfRef* args; CVMObject* arg; CVMObject* argTypes; CVMObject* argTypeClass; /* * cbAddr holds a native pointer as an int value * therefore change the type to CVMAddr which is 4 byte on * 32 bit platforms and 8 byte on 64 bit platforms */ CVMAddr cbAddr; int i, numArgs; CVMClassBlock* icb; /* instance class block */ CVMMethodBlock* imb; /* instance method block */ CVMInt32 override; /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {}); /* Get the methodblock pointer out of the Constructor object, which is the first argument to Constructor.newInstance(). NOTE use of the direct memory interface here. */ methodObject = CVMID_icellDirect(ee, &arguments[0].j.r); CVMassert(methodObject != NULL); /* Java code checks for NullPointerException */ declaredMb = CVMreflectGCUnsafeGetMethodBlock( ee, methodObject, CVMsystemClass(java_lang_reflect_Constructor_ArgumentException)); CVMassert(declaredMb != NULL); CVMD_fieldReadRef(methodObject, CVMoffsetOfjava_lang_reflect_Constructor_clazz, declaredClass); /* * Access member variable of type 'int' * and cast it to a native pointer. The java type 'int' only garanties * 32 bit, but because one slot is used as storage space and * a slot is 64 bit on 64 bit platforms, it is possible * to store a native pointer without modification of * java source code. This assumes that all places in the C-code * are catched which set/get this member. */ CVMD_fieldReadAddr(declaredClass, CVMoffsetOfjava_lang_Class_classBlockPointer, declaredCbAddr); declaredCb = (CVMClassBlock*) declaredCbAddr; /* * We need to make sure the class is initialized. */ if (!CVMcbInitializationDoneFlag(ee, declaredCb)) { CVMBool initialized;#ifdef CVM_TRACE CVMFrame *f = CVMeeGetCurrentFrame(ee);#endif TRACE_FRAMELESS_METHOD_RETURN(*p_mb, f); initialized = CVMreflectEnsureInitialized(ee, declaredCb); TRACE_FRAMELESS_METHOD_CALL(f, *p_mb, CVM_FALSE); if (!initialized) { return CNI_EXCEPTION; } /* recache methodObject since we become gcsafe. */ methodObject = CVMID_icellDirect(ee, &arguments[0].j.r); } obj = CVMID_icellDirect(ee, &arguments[1].j.r); CVMassert(obj != NULL); /* Constructor can't operate on null object. If object is null, an exception should have been thrown and we shouldn't have gotten here. */ /* Constructor methodblocks can't be static or virtual, and furthermore Jcc always sets constructors' method table slots to slot 0 (same as finalize()) so it is actually incorrect to do what should be a no-op CVMreflectGetObjectMethodblock. Let's settle for some assertions. */ CVMassert(!CVMmbIs(declaredMb, STATIC)); CVMassert(declaredCb == CVMobjectGetClass(obj)); icb = declaredCb; imb = declaredMb; /* * Access checking (unless overridden by Method) */ CVMD_fieldReadInt(methodObject, CVMoffsetOfjava_lang_reflect_AccessibleObject_override, override); if (!override) { if (!(CVMcbIs(declaredCb, PUBLIC) && CVMmbIs(declaredMb, PUBLIC))) { CVMClassBlock* exceptionCb = CVMsystemClass(java_lang_reflect_Constructor_AccessException); if (!CVMreflectCheckAccess(ee, declaredCb, CVMmbAccessFlags(declaredMb), icb, CVM_TRUE, exceptionCb)) { return CNI_EXCEPTION; /* exception */ } } } /* Allocate the transition frame. Note that this might become GC-safe, so we need to make sure we haven't screwed up our frame's top of stack. If we'd moved it down at this point, it's possible our arguments wouldn't get scanned and would therefore be GC'd. Also at this point note that the direct methodObject reference above is invalid. */ frame = (CVMFrame*)CVMpushTransitionFrame(ee, declaredMb); if (frame == NULL) { return CNI_EXCEPTION; /* exception already thrown */ } /* Push the object which was the second argument to Constructor.invoke() on the operand stack of the transition frame */ frame->topOfStack->ref = arguments[1].j.r; frame->topOfStack++; /* Obtain the arguments to Constructor.invoke() from the local variable section. Note that arguments, the "top of the operand stack", actually points to the bottom of the set of arguments; that is, arguments[0] corresponds to the first argument to this method, arguments[1] to the second, etc. */ /* Recache methodObject in case pushTransitionFrame caused GC */ methodObject = CVMID_icellDirect(ee, &arguments[0].j.r); CVMassert(methodObject != NULL); args = (CVMArrayOfRef*) CVMID_icellDirect(ee, &arguments[2].j.r); CVMD_fieldReadRef(methodObject, CVMoffsetOfjava_lang_reflect_Constructor_parameterTypes, argTypes); /* NOTE: number of arguments checked above in Java */ if (CVMD_arrayGetLength((CVMArrayOfRef*) argTypes) > 0) CVMassert(CVMD_arrayGetLength(args) == CVMD_arrayGetLength((CVMArrayOfRef*) argTypes)); numArgs = CVMD_arrayGetLength((CVMArrayOfRef*) argTypes); /* NOTE: should probably offer GC checkpoints every few arguments. However, will have to recache the direct pointers we hold if GC actually occurred. Also, stackmap won't be present for transition frame, but that probably doesn't matter since object arguments will get scanned from the previous frame's stack. */ for (i = 0; i < numArgs; i++) { CVMClassBlock* exceptionCb = CVMsystemClass(java_lang_reflect_Constructor_ArgumentException); CVMD_arrayReadRef(args, i, arg); CVMD_arrayReadRef((CVMArrayOfRef*) argTypes, i, argTypeClass); /* * Access member variable of type 'int' * and cast it to a native pointer. The java type 'int' only garanties * 32 bit, but because one slot is used as storage space and * a slot is 64 bit on 64 bit platforms, it is possible * to store a native pointer without modification of * java source code. This assumes that all places in the C-code * are catched which set/get this member. */ CVMD_fieldReadAddr(argTypeClass, CVMoffsetOfjava_lang_Class_classBlockPointer, cbAddr); if (!CVMreflectGCUnsafePushArg(ee, frame, arg, (CVMClassBlock*) cbAddr, exceptionCb)) { CVMpopFrame(&ee->interpreterStack, frame); return CNI_EXCEPTION; /* exception occurred */ } } /* Note we leave myFrame->topOfStack untouched, because it is decached by the interpreter when we return, but it is very important that we don't offer a GC-safe point after mutating the stack slot(s) corresponding to the return value because of possible changes of refness, which would make the stackmap incorrect. */ *p_mb = declaredMb; return CNI_NEW_TRANSITION_FRAME;}#endif /* CVM_REFLECT */CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Constructor_allocateUninitializedObject( CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){#ifdef CVM_REFLECT CVMObject* clazz; /* * Access member variable of type 'int' * and cast it to a native pointer. The java type 'int' only garanties * 32 bit, but because one slot is used as storage space and * a slot is 64 bit on 64 bit platforms, it is possible * to store a native pointer without modification of * java source code. This assumes that all places in the C-code * are catched which set/get this member. */ CVMAddr cbAddr; CVMClassBlock* cb; /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {}); /* This is a little scary, but should work. We reuse the Object stack slot reserved for the incoming java.lang.Class object for our return value. Note we don't change the "refness" of the stack slot so we should be okay even if we GC in unexpected places. We should also be okay in the case of GC'ing classes and classblocks, because the switch from the object being a Class to being an instance of that class is atomic with respect to GC, and in both cases we will be scanning the Class. */ clazz = CVMID_icellDirect(ee, &arguments[0].j.r); CVMD_fieldReadAddr(clazz, CVMoffsetOfjava_lang_Class_classBlockPointer, cbAddr); cb = (CVMClassBlock*) cbAddr; /* If we're are trying to instantiate an instance of java.lang.Class, then this should result in an IllegalAccessException. Don't bother allocating the unused object. Just throw the exception. */ if (cb == CVMsystemClass(java_lang_Class)) { CVMthrowIllegalAccessException(ee, NULL); return CNI_EXCEPTION; } if (CVMcbIs(cb, INTERFACE) || CVMcbIs(cb, ABSTRACT)) { CVMthrowInstantiationException(ee, "class type is interface or abstract"); return CNI_EXCEPTION; } CVMD_gcSafeExec(ee, { CVMID_allocNewInstance(ee, cb, &arguments[0].j.r); }); if (CVMID_icellIsNull(&arguments[0].j.r)) { CVMthrowOutOfMemoryError(ee, NULL); return CNI_EXCEPTION; } return CNI_SINGLE;#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Constructor_invokeConstructor(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMinvokeConstructor(ee, arguments, p_mb);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?