/*
* Copyright (c) 2012 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 in the LICENSE file that
* accompanied this code).
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/altHashing.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/linkResolver.hpp"
#ifndef SERIALGC
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#endif // SERIALGC
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/gcLocker.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceOop.hpp"
#include "oops/markOop.hpp"
#include "oops/methodOop.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
#include "oops/typeArrayOop.hpp"
#include "prims/jniCheck.hpp"
#include "prims/jniExport.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jfieldIDWorkaround.hpp"
#include "runtime/reflection.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/signature.hpp"
#include "runtime/vm_operations.hpp"
#include "services/runtimeService.hpp"
#include "trace/tracing.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/histogram.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
# include "thread_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
# include "thread_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
# include "thread_bsd.inline.hpp"
#endif
// The DT_RETURN_MARK macros create a scoped object to fire the dtrace
// '-return' probe regardless of the return path is taken out of the function.
// Methods that have multiple return paths use this to avoid having to
// instrument each return path. Methods that use CHECK or THROW must use this
// since those macros can cause an immedate uninstrumented return.
//
// In order to get the return value, a reference to the variable containing
// the return value must be passed to the contructor of the object, and
// the return value must be set before return (since the mark object has
// a reference to it).
//
// Example:
// DT_RETURN_MARK_DECL(SomeFunc, int);
// JNI_ENTRY(int, SomeFunc, ...)
// int return_value = 0;
// DT_RETURN_MARK(SomeFunc, int, (const int&)return_value);
// foo(CHECK_0)
// return_value = 5;
// return return_value;
// JNI_END
#ifndef USDT2
DTRACE_ONLY( \
class DTraceReturnProbeMark_##name { \
public: \
~DTraceReturnProbeMark_##name() { \
} \
} \
)
// Void functions are simpler since there's no return value
DTRACE_ONLY( \
class DTraceReturnProbeMark_##name { \
public: \
~DTraceReturnProbeMark_##name() { \
} \
} \
)
#else /* USDT2 */
DTRACE_ONLY( \
class DTraceReturnProbeMark_##name { \
public: \
~DTraceReturnProbeMark_##name() { \
probe; \
} \
} \
)
// Void functions are simpler since there's no return value
DTRACE_ONLY( \
class DTraceReturnProbeMark_##name { \
public: \
~DTraceReturnProbeMark_##name() { \
probe; \
} \
} \
)
#endif /* USDT2 */
// Place these macros in the function to mark the return. Non-void
// functions need the type and address of the return value.
// Use these to select distinct code for floating-point vs. non-floating point
// situations. Used from within common macros where we need slightly
#define COMMA ,
// (dtrace doesn't do FP yet)
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// out-of-line helpers for class jfieldIDWorkaround:
if (is_checked_jfieldID(id)) {
if (!klass_hash_ok(k, id)) {
return false;
}
}
} else {
#ifdef ASSERT
#else
#endif
}
}
if (offset <= small_offset_mask) {
// With compressed oops the most super class with nonstatic fields would
// be the owner of fields embedded in the header.
}
} else {
#if 0
#ifndef PRODUCT
{
}
#endif
#endif
return 0;
}
}
do {
// Could use a non-blocking query for identity_hash here...
return true;
} while (k != NULL);
return false;
}
if (VerifyJNIFields) {
if (is_checked_jfieldID(id)) {
"Bug in native code: jfieldID class must match object");
} else {
#if 0
#ifndef PRODUCT
if (Verbose) {
}
#endif
#endif
}
}
"Bug in native code: jfieldID offset must address interior of object");
}
// Pick a reasonable higher bound for local capacity requested
// for EnsureLocalCapacity and PushLocalFrame. We don't want it too
// high because a test (or very unusual application) may try to allocate
// that many handles and run out of swap space. An implementation is
// permitted to allocate more handles than the ensured capacity, so this
// value is set high enough to prevent compatibility problems.
// Wrapper to trace JNI functions
#ifdef ASSERT
public:
if (TraceJNICalls) {
}
}
};
public:
JNIHistogramElement(const char* name);
};
_name = elementName;
count +=1;
if ( (WarnOnStalledSpinLock > 0)
&& (count % WarnOnStalledSpinLock == 0)) {
warning("JNIHistogram_lock seems to be stalled");
}
}
}
if(JNIHistogram == NULL)
JNIHistogram->add_element(this);
}
/* There is a MT-race condition in VC++. So we need to make sure that that e has been initialized */ \
if (e != NULL) e->increment_count()
#else
#endif
// Implementation of JNI entries
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("DefineClass");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Since exceptions can be thrown, class initialization can take place
// if name is NULL no check for class name in .class stream has to be made.
// It's impossible to create this class; the name cannot fit
// into the constant pool.
}
}
// check whether the current caller thread holds the lock or not.
// If not, increment the corresponding counter
if (ObjectSynchronizer::
}
}
if (TraceClassResolution && k != NULL) {
}
return cls;
static bool first_time_FindClass = true;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("FindClass");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Remember if we are the first invocation of jni_FindClass
first_time_FindClass = false;
// Sanity check the name: it cannot be null or larger than the maximum size
// name we can fit in the constant pool.
}
//%note jni_3
// Find calling class
if (k.not_null()) {
// Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed
// in the correct class context.
thread);
if (HAS_PENDING_EXCEPTION) {
}
}
} else {
// We call ClassLoader.getSystemClassLoader to obtain the system class loader.
}
protection_domain, true, thread);
}
// If we were the first invocation of jni_FindClass, we enable compilation again
// rather than just allowing invocation counter to overflow and decay.
// Controlled by flag DelayCompilationDuringStartup.
if (first_time && !CompileTheWorld)
return result;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("FromReflectedMethod");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// method is a handle to a java.lang.reflect.Method object
int slot = 0;
} else {
}
// Make sure class is initialized before handing id's out to methods
return ret;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("FromReflectedField");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// field is a handle to a java.lang.reflect.Field object
// Make sure class is initialized before handing id's out to fields
// First check if this is a static field
if (modifiers & JVM_ACC_STATIC) {
// A jfieldID for a static field is a JNIid specifying the field holder and the offset within the klassOop
return ret;
}
// The slot is the index of the field description in the field-array
// The jfieldID is the offset of the field within the object
// It may also have hash bits for k, if VerifyJNIFields is turned on.
return ret;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
JNIWrapper("ToReflectedMethod");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (m->is_initializer()) {
} else {
}
return ret;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("GetSuperclass");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// primitive classes return NULL
// Rules of Class.getSuperClass as implemented by KLass::java_super:
// arrays return Object
// interfaces return NULL
// proper classes return Klass::super()
// return mirror for superclass
// super2 is the value computed by the compiler's getSuperClass intrinsic:
"java_super computation depends on interface, array, other super");
return obj;
JNIWrapper("IsSubclassOf");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
}
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("Throw");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("ThrowNew");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
instanceKlass* k = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz)));
// JNI functions only transform a pending async exception to a synchronous
// exception in ExceptionOccurred and ExceptionCheck calls, since
// delivering an async exception in other places won't change the native
// code's control flow and would be harmful when native code further calls
// JNI functions with a pending exception. Async exception is also checked
// during the call, so ExceptionOccurred/ExceptionCheck won't return
// false but deliver the async exception at the very end during
// state transition.
}
JNIWrapper("ExceptionOccurred");
#ifndef USDT2
#else /* USDT2 */
env);
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNIWrapper("ExceptionDescribe");
#ifndef USDT2
#else /* USDT2 */
env);
#endif /* USDT2 */
if (thread->has_pending_exception()) {
// Don't print anything if we are being killed.
} else {
}
ex,
THREAD);
// If an exception is thrown in the call it gets thrown away. Not much
// we can do with it. The native code that calls this, does not check
// for the exception - hence, it might still be in the thread when DestroyVM gets
// called, potentially causing a few asserts to trigger - since no pending exception
// is expected.
} else {
". Uncaught exception of type %s.",
}
}
}
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("ExceptionClear");
#ifndef USDT2
#else /* USDT2 */
env);
#endif /* USDT2 */
// The jni code might be using this API to clear java thrown exception.
// So just mark jvmti thread exception state as exception caught.
}
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("FatalError");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
thread->print_stack();
JNIWrapper("PushLocalFrame");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
//%note jni_11
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return JNI_ERR;
}
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNIWrapper("PopLocalFrame");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
//%note jni_11
if (new_handles != NULL) {
// As a sanity check we only release the handle blocks if the pop_frame_link is not NULL.
// This way code will still work if PopLocalFrame is called without a corresponding
// PushLocalFrame call. Note that we set the pop_frame_link to NULL explicitly, otherwise
// the release_block call will release the blocks.
}
#ifndef USDT2
#else /* USDT2 */
result);
#endif /* USDT2 */
return result;
JNIWrapper("NewGlobalRef");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
// Must be JNI_ENTRY (with HandleMark)
JNIWrapper("DeleteGlobalRef");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("DeleteLocalRef");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("IsSameObject");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNIWrapper("NewLocalRef");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNIWrapper("EnsureLocalCapacity");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
} else {
}
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
// Return the Handle Type
JNIWrapper("GetObjectRefType");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
else
#ifndef USDT2
#else /* USDT2 */
(void *) ret);
#endif /* USDT2 */
return ret;
protected:
virtual void get_bool () = 0;
virtual void get_char () = 0;
virtual void get_short () = 0;
virtual void get_byte () = 0;
virtual void get_int () = 0;
virtual void get_long () = 0;
virtual void get_float () = 0;
virtual void get_double () = 0;
virtual void get_object () = 0;
this->_return_type = T_ILLEGAL;
_arguments = NULL;
}
public:
inline void do_array(int begin, int end) { if (!is_return_type()) get_object(); } // do_array uses get_object -- there is no get_array
inline void do_void() { }
};
protected:
inline void get_bool() { _arguments->push_int(va_arg(_ap, jint)); } // bool is coerced to int when using va_arg
inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg
inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg
inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg
// each of these paths is exercized by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg
#ifdef va_copy
#else
#endif
}
public:
}
}
// Optimized path if we have the bitvector form of signature
else {
while ( 1 ) {
switch ( fingerprint & parameter_feature_mask ) {
case bool_parm:
case char_parm:
case short_parm:
case byte_parm:
case int_parm:
get_int();
break;
case obj_parm:
get_object();
break;
case long_parm:
get_long();
break;
case float_parm:
get_float();
break;
case double_parm:
get_double();
break;
case done_parm:
return;
break;
default:
break;
}
}
}
}
};
protected:
public:
}
}
// Optimized path if we have the bitvector form of signature
else {
while ( 1 ) {
switch ( fingerprint & parameter_feature_mask ) {
case bool_parm:
get_bool();
break;
case char_parm:
get_char();
break;
case short_parm:
get_short();
break;
case byte_parm:
get_byte();
break;
case int_parm:
get_int();
break;
case obj_parm:
get_object();
break;
case long_parm:
get_long();
break;
case float_parm:
get_float();
break;
case double_parm:
get_double();
break;
case done_parm:
return;
break;
default:
break;
}
}
}
}
};
enum JNICallType {
};
LinkResolver::resolve_interface_call(info, recv, recv_klass, spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
return info.selected_method();
}
LinkResolver::resolve_virtual_call(info, recv, recv_klass, spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
return info.selected_method();
}
static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
// Create object to hold arguments for the JavaCall, and associate it with
// the jni parser
// Fill out JavaCallArguments object
// Initialize result type
// Invoke the method. Result is returned as oop.
// Convert result
}
}
static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
}
int number_of_parameters;
{
// non-interface call -- for that little speed boost, don't handlize
if (call_type == JNI_VIRTUAL) {
// jni_GetMethodID makes sure class is linked and initialized
// so m should have a valid vtable index.
// k might be an arrayKlassOop but all vtables start at
// the same place. The cast is to avoid virtual call and assertion.
} else {
// final method
selected_method = m;
}
} else {
// JNI_NONVIRTUAL call
selected_method = m;
}
} else {
// interface call
if (itbl_index == -1) {
// the above may have grabbed a lock, 'm' and anything non-handlized can't be used again
}
}
}
// Create object to hold arguments for the JavaCall, and associate it with
// the jni parser
// handle arguments
// Fill out JavaCallArguments object
// Initialize result type
// Invoke the method. Result is returned as oop.
// Convert result
}
}
return ih;
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("AllocObject");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return ret;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
JNIWrapper("NewObjectA");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return obj;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("NewObjectV");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return obj;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("NewObject");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return obj;
JNIWrapper("GetObjectClass");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNIWrapper("IsInstanceOf");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (k != NULL) {
}
}
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
// %%%% This code should probably just call into a method in the LinkResolver
//
// The class should have been loaded (we have an instance of the class
// passed in) so the method and signature should already be in the symbol
// table. If they're not there, the method doesn't exist.
: name_str;
}
// Throw a NoSuchMethodError exception if we have an instance of a
// primitive java.lang.Class
}
// Make sure class is linked and initialized before handing id's out to
// methodOops.
methodOop m;
// Never search superclasses for constructors
if (klass->oop_is_instance()) {
} else {
m = NULL;
}
} else {
// Look up interfaces
}
}
}
return m->jmethod_id();
}
JNIWrapper("GetMethodID");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return ret;
JNIWrapper("GetStaticMethodID");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return ret;
//
// Calling Methods
//
#ifndef USDT2
\
\
\
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
JNI_END \
\
\
\
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
JNI_END \
\
\
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
#else /* USDT2 */
, EntryProbe, ReturnProbe) \
\
, ReturnProbe); \
\
\
EntryProbe; \
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
, EntryProbe, ReturnProbe) \
\
, ReturnProbe); \
\
\
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
, EntryProbe, ReturnProbe) \
\
, ReturnProbe); \
\
EntryProbe; \
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
#endif /* USDT2 */
JNIWrapper("CallVoidMethod");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("CallVoidMethodV");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args))
JNIWrapper("CallVoidMethodA");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
\
\
jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \
\
(const ResultType&)ret);\
\
return ret;\
JNI_END \
\
jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \
(const ResultType&)ret);\
\
return ret;\
JNI_END \
\
jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
#else /* USDT2 */
, EntryProbe, ReturnProbe) \
\
, ReturnProbe);\
\
jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \
\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
, EntryProbe, ReturnProbe) \
\
, ReturnProbe);\
\
jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \
\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
, EntryProbe, ReturnProbe) \
\
, ReturnProbe);\
\
jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \
\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
#endif /* USDT2 */
JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...))
JNIWrapper("CallNonvirtualVoidMethod");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args))
JNIWrapper("CallNonvirtualVoidMethodV");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args))
JNIWrapper("CallNonvirtualVoidMethodA");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
\
\
\
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
JNI_END \
\
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
JNI_END \
\
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
#else /* USDT2 */
, EntryProbe, ResultProbe) \
\
, ResultProbe); \
\
\
EntryProbe; \
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
, EntryProbe, ResultProbe) \
\
, ResultProbe); \
\
\
EntryProbe; \
ResultType ret = 0;\
(const ResultType&)ret);\
\
/* Make sure class is initialized before trying to invoke its method */ \
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
, EntryProbe, ResultProbe) \
\
, ResultProbe); \
\
\
EntryProbe; \
ResultType ret = 0;\
(const ResultType&)ret);\
\
return ret;\
// the runtime type of subword integral basic types is integer
// Float and double probes don't return value because dtrace doesn't currently support it
#endif /* USDT2 */
JNIWrapper("CallStaticVoidMethod");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args))
JNIWrapper("CallStaticVoidMethodV");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args))
JNIWrapper("CallStaticVoidMethodA");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
//
// Accessing Fields
//
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("GetFieldID");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// The class should have been loaded (we have an instance of the class
// passed in) so the field and signature should already be in the symbol
// table. If they're not there, the field doesn't exist.
}
// Make sure class is initialized before handing id's out to fields
}
// A jfieldID for a non-static field is simply the offset of the field within the instanceOop
// It may also have hash bits for k, if VerifyJNIFields is turned on.
return ret;
JNIWrapper("GetObjectField");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Keep JVMTI addition small and only check enabled flag here.
// jni_GetField_probe() assumes that is okay to create handles.
if (JvmtiExport::should_post_field_access()) {
}
#ifndef SERIALGC
// If G1 is enabled and we are accessing the value of the referent
// field in a reference object then we need to register a non-null
// referent with the SATB barrier.
if (UseG1GC) {
bool needs_barrier = false;
needs_barrier = true;
}
if (needs_barrier) {
}
}
#endif // SERIALGC
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
#ifndef USDT2
\
\
\
\
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_GetField_probe_nh() assumes that is not okay to create handles */ \
/* and creates a ResetNoHandleMark. */ \
if (JvmtiExport::should_post_field_access()) { \
} \
return ret; \
#else /* USDT2 */
, EntryProbe, ReturnProbe) \
\
, ReturnProbe); \
\
\
EntryProbe; \
\
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_GetField_probe_nh() assumes that is not okay to create handles */ \
/* and creates a ResetNoHandleMark. */ \
if (JvmtiExport::should_post_field_access()) { \
} \
return ret; \
// Float and double probes don't return value because dtrace doesn't currently support it
#endif /* USDT2 */
return (address)jni_GetBooleanField;
}
return (address)jni_GetByteField;
}
return (address)jni_GetCharField;
}
return (address)jni_GetShortField;
}
return (address)jni_GetIntField;
}
return (address)jni_GetLongField;
}
return (address)jni_GetFloatField;
}
return (address)jni_GetDoubleField;
}
JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
JNIWrapper("SetObjectField");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Keep JVMTI addition small and only check enabled flag here.
// jni_SetField_probe_nh() assumes that is not okay to create handles
// and creates a ResetNoHandleMark.
if (JvmtiExport::should_post_field_modification()) {
field_value.l = value;
o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value);
}
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
#ifndef USDT2
\
JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
\
FP_SELECT_##Result( \
\
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_SetField_probe_nh() assumes that is not okay to create handles */ \
/* and creates a ResetNoHandleMark. */ \
if (JvmtiExport::should_post_field_modification()) { \
o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
} \
#else /* USDT2 */
, EntryProbe, ReturnProbe) \
\
JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
\
EntryProbe; \
\
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_SetField_probe_nh() assumes that is not okay to create handles */ \
/* and creates a ResetNoHandleMark. */ \
if (JvmtiExport::should_post_field_modification()) { \
o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
} \
ReturnProbe; \
// Float and double probes don't return value because dtrace doesn't currently support it
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic))
JNIWrapper("ToReflectedField");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
bool found = false;
if (isStatic) {
// Static field. The fieldID a JNIid specifying the field holder and the offset within the klassOop.
} else {
// Non-static field. The fieldID is really the offset of the field within the instanceOop.
}
return ret;
//
// Accessing Static Fields
//
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("GetStaticFieldID");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// The class should have been loaded (we have an instance of the class
// passed in) so the field and signature should already be in the symbol
// table. If they're not there, the field doesn't exist.
}
// Make sure class is initialized before handing id's out to static fields
}
// A jfieldID for a static field is a JNIid specifying the field holder and the offset within the klassOop
return ret;
JNIWrapper("GetStaticObjectField");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Keep JVMTI addition small and only check enabled flag here.
// jni_GetField_probe() assumes that is okay to create handles.
if (JvmtiExport::should_post_field_access()) {
}
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
#ifndef USDT2
\
\
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_GetField_probe() assumes that is okay to create handles. */ \
if (JvmtiExport::should_post_field_access()) { \
} \
return ret;\
#else /* USDT2 */
, EntryProbe, ReturnProbe) \
\
, ReturnProbe); \
\
EntryProbe; \
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_GetField_probe() assumes that is okay to create handles. */ \
if (JvmtiExport::should_post_field_access()) { \
} \
return ret;\
, HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN(_ret_ref))
, HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN(_ret_ref) )
, HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN(_ret_ref) )
, HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN(_ret_ref) )
, HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICINTFIELD_RETURN(_ret_ref) )
, HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN(_ret_ref) )
// Float and double probes don't return value because dtrace doesn't currently support it
, HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN() )
, HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN() )
#endif /* USDT2 */
JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value))
JNIWrapper("SetStaticObjectField");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Keep JVMTI addition small and only check enabled flag here.
// jni_SetField_probe() assumes that is okay to create handles.
if (JvmtiExport::should_post_field_modification()) {
field_value.l = value;
JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value);
}
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
#ifndef USDT2
\
JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \
FP_SELECT_##Result( \
\
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_SetField_probe() assumes that is okay to create handles. */ \
if (JvmtiExport::should_post_field_modification()) { \
JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
} \
#else /* USDT2 */
, EntryProbe, ReturnProbe) \
\
JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \
EntryProbe; \
\
/* Keep JVMTI addition small and only check enabled flag here. */ \
/* jni_SetField_probe() assumes that is okay to create handles. */ \
if (JvmtiExport::should_post_field_modification()) { \
JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
} \
// Float and double probes don't return value because dtrace doesn't currently support it
#endif /* USDT2 */
//
// String Operations
//
// Unicode Interface
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("NewString");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return ret;
JNIWrapper("GetStringLength");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNIWrapper("GetStringChars");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
//%note jni_5
}
if (s_len > 0) {
}
#ifndef USDT2
#else /* USDT2 */
buf);
#endif /* USDT2 */
return buf;
JNIWrapper("ReleaseStringChars");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
//%note jni_6
// Since String objects are supposed to be immutable, don't copy any
// new data back. A bad user will have to go after the char array.
}
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
// UTF Interface
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("NewStringUTF");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return ret;
JNIWrapper("GetStringUTFLength");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNIWrapper("GetStringUTFChars");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
result);
#endif /* USDT2 */
return result;
JNIWrapper("ReleaseStringUTFChars");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
}
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("GetArrayLength");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
//
// Object Array Operations
//
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement))
JNIWrapper("NewObjectArray");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
}
}
return ret;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNIWrapper("GetObjectArrayElement");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (a->is_within_bounds(index)) {
return ret;
} else {
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
JNIWrapper("SetObjectArrayElement");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (a->is_within_bounds(index)) {
a->obj_at_put(index, v);
} else {
}
} else {
}
#ifndef USDT2
\
\
\
return ret;\
#else /* USDT2 */
\
, ReturnProbe); \
\
EntryProbe; \
\
return ret;\
#endif /* USDT2 */
// Return an address which will fault if the caller writes to it.
static char* get_bad_address() {
if (bad_address == NULL) {
if (bad_address != NULL) {
/*is_committed*/false);
}
}
return bad_address;
}
#ifndef USDT2
\
/* allocate an chunk of memory in c land */ \
ElementType* result; \
if (len == 0) { \
/* Empty array: legal but useless, can't return NULL. \
* Return a pointer to something useless. \
* Avoid asserts in typeArrayOop. */ \
} else { \
/* copy the array to the c chunk */ \
} \
return result; \
#else /* USDT2 */
, EntryProbe, ReturnProbe) \
\
EntryProbe; \
/* allocate an chunk of memory in c land */ \
ElementType* result; \
if (len == 0) { \
/* Empty array: legal but useless, can't return NULL. \
* Return a pointer to something useless. \
* Avoid asserts in typeArrayOop. */ \
} else { \
/* copy the array to the c chunk */ \
} \
ReturnProbe; \
return result; \
// Float and double probes don't return value because dtrace doesn't currently support it
#endif /* USDT2 */
#ifndef USDT2
\
JNI_QUICK_ENTRY(void, \
if (len != 0) { /* Empty array: nothing to free or copy. */ \
} \
} \
} \
#else /* USDT2 */
, EntryProbe, ReturnProbe);\
\
JNI_QUICK_ENTRY(void, \
EntryProbe; \
if (len != 0) { /* Empty array: nothing to free or copy. */ \
} \
} \
} \
ReturnProbe; \
#endif /* USDT2 */
#ifndef USDT2
\
JNI_ENTRY(void, \
if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \
} else { \
if (len > 0) { \
} \
} \
#else /* USDT2 */
, EntryProbe, ReturnProbe); \
, ReturnProbe); \
\
JNI_ENTRY(void, \
EntryProbe; \
if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \
} else { \
if (len > 0) { \
} \
} \
#endif /* USDT2 */
#ifndef USDT2
\
JNI_ENTRY(void, \
if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \
} else { \
if (len > 0) { \
} \
} \
#else /* USDT2 */
, EntryProbe, ReturnProbe); \
,ReturnProbe); \
\
JNI_ENTRY(void, \
EntryProbe; \
if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \
} else { \
if (len > 0) { \
} \
} \
#endif /* USDT2 */
//
// Interception of natives
//
// The RegisterNatives call being attempted tried to register with a method that
// is not native. Ask JVM TI what prefixes have been specified. Then check
// to see if the native method is now wrapped with the prefixes. See the
// SetNativeMethodPrefix(es) functions in the JVM TI Spec for details.
int prefix_count;
for (int i = 0; i < prefix_count; i++) {
// try adding this prefix to the method name and see if it matches another method name
if (trial_name == NULL) {
continue; // no such symbol, so this prefix wasn't used, try the next prefix
}
continue; // signature doesn't match, try the next prefix
}
return method; // wahoo, we found a prefixed version of the method, return it
}
// found as non-native, so prefix is good, add it, probably just need more prefixes
}
return NULL; // not found
}
}
// trying to register to a non-native method, see if a JVM TI agent has added prefix(es)
}
}
} else {
}
if (PrintJNIResolving) {
}
return true;
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
const JNINativeMethod *methods,
JNIWrapper("RegisterNatives");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// The class should have been loaded (we have an instance of the class
// passed in) so the method and signature should already be in the symbol
// table. If they're not there, the method doesn't exist.
// Must return negative value on failure
}
if (!res) {
ret = -1;
break;
}
}
return ret;
JNIWrapper("UnregisterNatives");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
//%note jni_2
if (m->is_native()) {
m->clear_native_function();
}
}
}
#ifndef USDT2
#else /* USDT2 */
0);
#endif /* USDT2 */
return 0;
//
// Monitor functions
//
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// If the object is null, we can't do anything with it
}
return ret;
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Don't do anything with a null object
}
return ret;
//
// Extensions
//
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf))
JNIWrapper("GetStringRegion");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
} else {
if (len > 0) {
}
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf))
JNIWrapper("GetStringUTFRegion");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
} else {
//%note jni_7
if (len > 0) {
} else {
// JDK null-terminates the buffer even in len is zero
buf[0] = 0;
}
}
}
JNIWrapper("GetPrimitiveArrayCritical");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
}
if (a->is_objArray()) {
} else {
}
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode))
JNIWrapper("ReleasePrimitiveArrayCritical");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// The array, carray and mode arguments are ignored
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("GetStringCritical");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
}
if (s_len > 0) {
} else {
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return ret;
JNIWrapper("ReleaseStringCritical");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// The str and chars arguments are ignored
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("jni_NewWeakGlobalRef");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
// Must be JNI_ENTRY (with HandleMark)
JNIWrapper("jni_DeleteWeakGlobalRef");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
);
#endif /* USDT2 */
JNIWrapper("jni_ExceptionCheck");
#ifndef USDT2
#else /* USDT2 */
env);
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
// Initialization state for three routines below relating to
// java.nio.DirectBuffers
jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
}
return result;
}
// These lookups are done with the NULL (bootstrap) ClassLoader to
// circumvent any security checks that would be done by jni_FindClass.
{
if ((directBufferClass = lookupOne(env, "sun/nio/ch/DirectBuffer", thread)) == NULL) { return false; }
if ((directByteBufferClass = lookupOne(env, "java/nio/DirectByteBuffer", thread)) == NULL) { return false; }
return true;
}
return false;
}
if (!lookupDirectBufferClasses(env)) {
return false;
}
// Make global references for these
// Get needed field and method IDs
if ((directByteBufferConstructor == NULL) ||
(directBufferAddressField == NULL) ||
(bufferCapacityField == NULL)) {
return false;
}
} else {
// Set state as yield_all can call os:sleep. On Solaris, yield_all calls
// os::sleep which requires the VM state transition. On other platforms, it
// is not necessary. The following call to change the VM state is purposely
// put inside the loop to avoid potential deadlock when multiple threads
// try to call this method. See 6791815 for more details.
}
}
return !directBufferSupportInitializeFailed;
}
{
// thread_from_jni_environment() will block if VM is gone.
JNIWrapper("jni_NewDirectByteBuffer");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
NULL);
#endif /* USDT2 */
return NULL;
}
}
// Being paranoid about accidental sign extension on address
// NOTE that package-private DirectByteBuffer constructor currently
// takes int capacity
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
}
#ifndef USDT2
#else /* USDT2 */
, HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN((void*) _ret_ref));
#endif /* USDT2 */
{
// thread_from_jni_environment() will block if VM is gone.
JNIWrapper("jni_GetDirectBufferAddress");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return 0;
}
}
return 0;
}
return ret;
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
{
// thread_from_jni_environment() will block if VM is gone.
JNIWrapper("jni_GetDirectBufferCapacity");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
ret = 0;
return ret;
}
}
return -1;
}
return -1;
}
// NOTE that capacity is currently an int in the implementation
return ret;
}
JNIWrapper("GetVersion");
#ifndef USDT2
#else /* USDT2 */
env);
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return CurrentVersion;
JNIWrapper("jni_GetJavaVM");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
JNI_OK);
#endif /* USDT2 */
return JNI_OK;
// Structure containing all jni functions
NULL,
NULL,
NULL,
NULL,
// New 1_6 features
};
// For jvmti use to modify jni function table.
// Java threads in native contiues to run until it is transitioned
// to VM at safepoint. Before the transition or before it is blocked
// for safepoint it may access jni function table. VM could crash if
// any java thread access the jni function table in the middle of memcpy.
// To avoid this each function pointers are copied automically.
for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
}
}
void quicken_jni_functions() {
// Replace Get<Primitive>Field with fast versions
// windows x86 currently needs SEH wrapper and the gain of the fast
// versions currently isn't certain for server vm on uniprocessor.
#endif
) {
}
}
}
}
}
}
}
}
}
}
// Returns the function structure
if (CheckJNICalls) return jni_functions_check();
return &jni_NativeInterface;
}
// Returns the function structure
return &jni_NativeInterface;
}
// Invocation API
// Forward declaration
extern const struct JNIInvokeInterface_ jni_InvokeInterface;
// Global invocation API vars
// Indicate whether it is safe to recreate VM
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
args_);
#endif /* USDT2 */
}
// 1.1 style no longer supported in hotspot.
// According the JNI spec, we should update args->version on return.
// We also use the structure to communicate with launcher about default
// stack size.
// javaStackSize is int in arguments structure
}
return ret;
}
#ifndef PRODUCT
#include "gc_implementation/shared/gcTimer.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "utilities/quickSort.hpp"
void execute_internal_vm_tests() {
if (ExecuteInternalVMTests) {
}
}
#endif
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// We're about to use Atomic::xchg for synchronization. Some Zero
// platforms use the GCC builtin __sync_lock_test_and_set for this,
// but __sync_lock_test_and_set is not guaranteed to do what we want
// on all architectures. So we check it works before relying on it.
{
jint a = 0xcafebabe;
void *c = &a;
assert(c == &b && d == &a, "Atomic::xchg_ptr() works");
}
#endif // ZERO && ASSERT
// At the moment it's only possible to have one Java VM,
// since some of the runtime state is in global variables.
// We cannot use our mutex locks here, since they only work on
// Threads. We do an atomic compare and exchange to ensure only
// one thread can call this method at a time
// on a multiprocessor, and at this stage of initialization the os::is_MP
// function used to determine this will always return false. Atomic::xchg
// does not have this problem.
return JNI_ERR; // already created, or create attempt in progress
}
return JNI_ERR; // someone tried and failed and retry not allowed.
}
/**
* Certain errors during initialization are recoverable and do not
* prevent this method from being called again at a later time
* (perhaps with different arguments). However, at a certain
* point during initialization if an error occurs we cannot allow
* this function to be called again (or it will crash). In those
* situations, the 'canTryAgain' flag is set to false, which atomically
* sets safe_to_recreate_vm to 1, such that any new call to
* JNI_CreateJavaVM will immediately fail using the above logic.
*/
bool can_try_again = true;
/* thread is thread_in_vm here */
// Tracks the time application was running before GC
// Notify JVMTI
if (JvmtiExport::should_post_thread_life()) {
}
if (event.should_commit()) {
}
// Check if we should compile all classes on bootclasspath
// Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.
} else {
if (can_try_again) {
// reset safe_to_recreate_vm to 1 so that retrial would be possible
safe_to_recreate_vm = 1;
}
// Creation failed. We must reset vm_created
*vm = 0;
// reset vm_created last to avoid race condition. Use OrderAccess to
// control both compiler and architectural-based reordering.
}
return result;
}
#ifndef USDT2
#endif /* !USDT2 */
_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) {
// See bug 4367188, the wrapper can sometimes cause VM crashes
// JNIWrapper("GetCreatedJavaVMs");
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (vm_created) {
} else {
}
#ifndef USDT2
#else /* USDT2 */
JNI_OK);
#endif /* USDT2 */
return JNI_OK;
}
extern "C" {
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
vm);
#endif /* USDT2 */
if (!vm_created) {
return res;
}
JNIWrapper("DestroyJavaVM");
return res;
}
// Since this is not a JVM_ENTRY we have to set the thread state manually before entering.
if (Threads::destroy_vm()) {
// Should not change thread state, VM is gone
vm_created = false;
return res;
} else {
return res;
}
}
// Check below commented out from JDK1.2fcs as well
/*
if (args && (args->version != JNI_VERSION_1_1 || args->version != JNI_VERSION_1_2)) {
return JNI_EVERSION;
}
*/
if (t != NULL) {
// If the thread has been attached this operation is a no-op
return JNI_OK;
}
// Create a thread and mark it as attaching so it will be skipped by the
// ThreadsListEnumerator - see CR 6404306
// Set correct safepoint info. The thread is going to call into Java when
// initializing the Java level thread object. Hence, the correct state must
// be set in order for the Safepoint code to deal with it correctly.
// Must do this before initialize_thread_local_storage
delete thread;
return JNI_ERR;
}
// Enable stack overflow checks
// Crucial that we do not have a safepoint check for this thread, since it has
// not been added to the Thread list yet.
// This must be inside this lock in order to get FullGCALot to work properly, i.e., to
// avoid this thread trying to do a GC before it is added to the thread-list
Threads_lock->unlock();
}
// Create thread group and name info from attach arguments
}
// Create Java level thread object and attach it to this thread
bool attach_failed = false;
{
if (HAS_PENDING_EXCEPTION) {
// cleanup outside the handle mark.
attach_failed = true;
}
}
if (attach_failed) {
// Added missing cleanup
return JNI_ERR;
}
// mark the thread as no longer attaching
// this uses a fence to push the change through so we don't have
// to regrab the threads_lock
// Set java thread status.
// Notify the debugger
if (JvmtiExport::should_post_thread_life()) {
}
if (event.should_commit()) {
}
// Now leaving the VM, so change thread_state. This is normally automatically taken care
// of in the JVM_ENTRY. But in this situation we have to do it manually. Notice, that by
// using ThreadStateTransition::transition, we do a callback to the safepoint code if
// needed.
// Perform any platform dependent FPU setup
return JNI_OK;
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (!vm_created) {
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return JNI_ERR;
}
JNIWrapper("AttachCurrentThread");
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
}
#ifndef USDT2
#else /* USDT2 */
vm);
#endif /* USDT2 */
JNIWrapper("DetachCurrentThread");
// If the thread has been deattacted the operations is a no-op
#ifndef USDT2
#else /* USDT2 */
JNI_OK);
#endif /* USDT2 */
return JNI_OK;
}
if (thread->has_last_Java_frame()) {
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
// Can't detach a thread that's running java, that can't work.
return JNI_ERR;
}
// Safepoint support. Have to do call-back to safepoint code, if in the
// middel of a safepoint operation
// XXX: Note that JavaThread::exit() call below removes the guards on the
// stack pages set up via enable_stack_{red,yellow}_zone() calls
// above in jni_AttachCurrentThread. Unfortunately, while the setting
// of the guards is visible in jni_AttachCurrentThread above,
// the removal of the guards is buried below in JavaThread::exit()
// here. The abstraction should be more symmetrically either exposed
// or hidden (e.g. it could probably be hidden in the same
// (platform-dependent) methods where we do alternate stack
// maintenance work?)
delete thread;
#ifndef USDT2
#else /* USDT2 */
JNI_OK);
#endif /* USDT2 */
return JNI_OK;
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (!vm_created) {
ret = JNI_EDETACHED;
return ret;
}
return ret;
}
#ifndef JVMPI_VERSION_1
// need these in order to be polite about older agents
#endif // !JVMPI_VERSION_1
return ret;
} else if (version == JVMPI_VERSION_1 ||
version == JVMPI_VERSION_1_1 ||
version == JVMPI_VERSION_1_2) {
ret = JNI_EVERSION;
return ret;
ret = JNI_EVERSION;
return ret;
} else {
ret = JNI_EVERSION;
return ret;
}
} else {
ret = JNI_EDETACHED;
return ret;
}
}
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
if (!vm_created) {
#ifndef USDT2
#else /* USDT2 */
#endif /* USDT2 */
return JNI_ERR;
}
JNIWrapper("AttachCurrentThreadAsDaemon");
#ifndef USDT2
#else /* USDT2 */
ret);
#endif /* USDT2 */
return ret;
}
} // End extern "C"
NULL,
NULL,
NULL,
};