7198429: need checked categorization of caller-sensitive methods in the JDK

Reviewed-by: kvn, jrose
This commit is contained in:
Christian Thalinger 2013-03-25 17:13:26 -07:00
parent e4b1cf5f02
commit 6964a690ed
18 changed files with 413 additions and 305 deletions

View File

@ -790,6 +790,17 @@ int ciMethod::scale_count(int count, float prof_factor) {
return count;
}
// ------------------------------------------------------------------
// ciMethod::is_special_get_caller_class_method
//
bool ciMethod::is_ignored_by_security_stack_walk() const {
check_is_loaded();
VM_ENTRY_MARK;
return get_Method()->is_ignored_by_security_stack_walk();
}
// ------------------------------------------------------------------
// invokedynamic support

View File

@ -166,8 +166,9 @@ class ciMethod : public ciMetadata {
// Code size for inlining decisions.
int code_size_for_inlining();
bool force_inline() { return get_Method()->force_inline(); }
bool dont_inline() { return get_Method()->dont_inline(); }
bool caller_sensitive() { return get_Method()->caller_sensitive(); }
bool force_inline() { return get_Method()->force_inline(); }
bool dont_inline() { return get_Method()->dont_inline(); }
int comp_level();
int highest_osr_comp_level();
@ -264,6 +265,9 @@ class ciMethod : public ciMetadata {
int instructions_size();
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
// Stack walking support
bool is_ignored_by_security_stack_walk() const;
// JSR 292 support
bool is_method_handle_intrinsic() const;
bool is_compiled_lambda_form() const;

View File

@ -1735,9 +1735,14 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
Symbol* name) {
vmSymbols::SID sid = vmSymbols::find_sid(name);
// Privileged code can use all annotations. Other code silently drops some.
bool privileged = loader_data->is_the_null_class_loader_data() ||
loader_data->is_anonymous();
const bool privileged = loader_data->is_the_null_class_loader_data() ||
loader_data->is_ext_class_loader_data() ||
loader_data->is_anonymous();
switch (sid) {
case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_reflect_CallerSensitive_signature):
if (_location != _in_method) break; // only allow for methods
if (!privileged) break; // only allow in privileged code
return _method_CallerSensitive;
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature):
if (_location != _in_method) break; // only allow for methods
if (!privileged) break; // only allow in privileged code
@ -1775,6 +1780,8 @@ ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
}
void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
if (has_annotation(_method_CallerSensitive))
m->set_caller_sensitive(true);
if (has_annotation(_method_ForceInline))
m->set_force_inline(true);
if (has_annotation(_method_DontInline))

View File

@ -119,6 +119,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
enum Location { _in_field, _in_method, _in_class };
enum ID {
_unknown = 0,
_method_CallerSensitive,
_method_ForceInline,
_method_DontInline,
_method_LambdaForm_Compiled,

View File

@ -321,6 +321,13 @@ ClassLoaderData::~ClassLoaderData() {
}
}
/**
* Returns true if this class loader data is for the extension class loader.
*/
bool ClassLoaderData::is_ext_class_loader_data() const {
return SystemDictionary::is_ext_class_loader(class_loader());
}
Metaspace* ClassLoaderData::metaspace_non_null() {
assert(!DumpSharedSpaces, "wrong metaspace!");
// If the metaspace has not been allocated, create a new one. Might want

View File

@ -191,6 +191,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
bool is_the_null_class_loader_data() const {
return this == _the_null_class_loader_data;
}
bool is_ext_class_loader_data() const;
// The Metaspace is created lazily so may be NULL. This
// method will allocate a Metaspace if needed.

View File

@ -1050,15 +1050,16 @@ class java_lang_invoke_MemberName: AllStatic {
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
enum {
MN_IS_METHOD = 0x00010000, // method (not constructor)
MN_IS_CONSTRUCTOR = 0x00020000, // constructor
MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type
MN_IS_METHOD = 0x00010000, // method (not constructor)
MN_IS_CONSTRUCTOR = 0x00020000, // constructor
MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
// The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
MN_SEARCH_SUPERCLASSES = 0x00100000, // walk super classes
MN_SEARCH_INTERFACES = 0x00200000 // walk implemented interfaces
MN_SEARCH_SUPERCLASSES = 0x00100000, // walk super classes
MN_SEARCH_INTERFACES = 0x00200000 // walk implemented interfaces
};
// Accessors for code generation:

View File

@ -146,6 +146,17 @@ bool SystemDictionary::is_parallelDefine(Handle class_loader) {
}
return false;
}
/**
* Returns true if the passed class loader is the extension class loader.
*/
bool SystemDictionary::is_ext_class_loader(Handle class_loader) {
if (class_loader.is_null()) {
return false;
}
return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
}
// ----------------------------------------------------------------------------
// Resolving of classes

View File

@ -106,6 +106,7 @@ class SymbolPropertyTable;
do_klass(ThreadDeath_klass, java_lang_ThreadDeath, Pre ) \
do_klass(Exception_klass, java_lang_Exception, Pre ) \
do_klass(RuntimeException_klass, java_lang_RuntimeException, Pre ) \
do_klass(SecurityManager_klass, java_lang_SecurityManager, Pre ) \
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \
do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \
@ -138,13 +139,14 @@ class SymbolPropertyTable;
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
do_klass(lambda_MagicLambdaImpl_klass, java_lang_invoke_MagicLambdaImpl, Opt ) \
do_klass(lambda_MagicLambdaImpl_klass, java_lang_invoke_MagicLambdaImpl, Opt ) \
do_klass(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt ) \
do_klass(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
do_klass(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
do_klass(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt ) \
do_klass(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15 ) \
do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15 ) \
do_klass(reflect_CallerSensitive_klass, sun_reflect_CallerSensitive, Opt ) \
\
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292 ) \
@ -628,12 +630,15 @@ private:
static bool is_parallelCapable(Handle class_loader);
static bool is_parallelDefine(Handle class_loader);
public:
static bool is_ext_class_loader(Handle class_loader);
private:
static Klass* find_shared_class(Symbol* class_name);
// Setup link to hierarchy
static void add_to_hierarchy(instanceKlassHandle k, TRAPS);
private:
// We pass in the hashtable index so we can calculate it outside of
// the SystemDictionary_lock.

View File

@ -91,6 +91,7 @@
template(java_lang_StringBuffer, "java/lang/StringBuffer") \
template(java_lang_StringBuilder, "java/lang/StringBuilder") \
template(java_lang_CharSequence, "java/lang/CharSequence") \
template(java_lang_SecurityManager, "java/lang/SecurityManager") \
template(java_security_AccessControlContext, "java/security/AccessControlContext") \
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
template(java_io_OutputStream, "java/io/OutputStream") \
@ -211,6 +212,8 @@
template(sun_reflect_SerializationConstructorAccessorImpl, "sun/reflect/SerializationConstructorAccessorImpl") \
template(sun_reflect_DelegatingClassLoader, "sun/reflect/DelegatingClassLoader") \
template(sun_reflect_Reflection, "sun/reflect/Reflection") \
template(sun_reflect_CallerSensitive, "sun/reflect/CallerSensitive") \
template(sun_reflect_CallerSensitive_signature, "Lsun/reflect/CallerSensitive;") \
template(checkedExceptions_name, "checkedExceptions") \
template(clazz_name, "clazz") \
template(exceptionTypes_name, "exceptionTypes") \
@ -343,6 +346,7 @@
template(contextClassLoader_name, "contextClassLoader") \
template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \
template(isPrivileged_name, "isPrivileged") \
template(getClassContext_name, "getClassContext") \
template(wait_name, "wait") \
template(checkPackageAccess_name, "checkPackageAccess") \
template(stackSize_name, "stackSize") \
@ -463,6 +467,7 @@
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
template(void_object_signature, "()Ljava/lang/Object;") \
template(void_class_signature, "()Ljava/lang/Class;") \
template(void_class_array_signature, "()[Ljava/lang/Class;") \
template(void_string_signature, "()Ljava/lang/String;") \
template(object_array_object_signature, "([Ljava/lang/Object;)Ljava/lang/Object;") \
template(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
@ -705,9 +710,8 @@
do_intrinsic(_getLength, java_lang_reflect_Array, getLength_name, object_int_signature, F_SN) \
do_name( getLength_name, "getLength") \
\
do_intrinsic(_getCallerClass, sun_reflect_Reflection, getCallerClass_name, getCallerClass_signature, F_SN) \
do_intrinsic(_getCallerClass, sun_reflect_Reflection, getCallerClass_name, void_class_signature, F_SN) \
do_name( getCallerClass_name, "getCallerClass") \
do_signature(getCallerClass_signature, "(I)Ljava/lang/Class;") \
\
do_intrinsic(_newArray, java_lang_reflect_Array, newArray_name, newArray_signature, F_SN) \
do_name( newArray_name, "newArray") \

View File

@ -967,6 +967,32 @@ bool Method::should_not_be_cached() const {
return false;
}
/**
* Returns true if this is one of the specially treated methods for
* security related stack walks (like Reflection.getCallerClass).
*/
bool Method::is_ignored_by_security_stack_walk() const {
const bool use_new_reflection = JDK_Version::is_gte_jdk14x_version() && UseNewReflection;
assert(intrinsic_id() != vmIntrinsics::_invoke || Universe::reflect_invoke_cache()->is_same_method((Method*)this), "sanity");
if (intrinsic_id() == vmIntrinsics::_invoke) {
// This is Method.invoke() -- ignore it
return true;
}
if (use_new_reflection &&
method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) {
// This is an auxilary frame -- ignore it
return true;
}
if (is_method_handle_intrinsic() || is_compiled_lambda_form()) {
// This is an internal adapter frame for method handles -- ignore it
return true;
}
return false;
}
// Constant pool structure for invoke methods:
enum {
_imcp_invoke_name = 1, // utf8: 'invokeExact', etc.
@ -1178,13 +1204,13 @@ vmSymbols::SID Method::klass_id_for_intrinsics(Klass* holder) {
// because we are not loading from core libraries
// exception: the AES intrinsics come from lib/ext/sunjce_provider.jar
// which does not use the class default class loader so we check for its loader here
if ((InstanceKlass::cast(holder)->class_loader() != NULL) &&
InstanceKlass::cast(holder)->class_loader()->klass()->name() != vmSymbols::sun_misc_Launcher_ExtClassLoader()) {
InstanceKlass* ik = InstanceKlass::cast(holder);
if ((ik->class_loader() != NULL) && !SystemDictionary::is_ext_class_loader(ik->class_loader())) {
return vmSymbols::NO_SID; // regardless of name, no intrinsics here
}
// see if the klass name is well-known:
Symbol* klass_name = InstanceKlass::cast(holder)->name();
Symbol* klass_name = ik->name();
return vmSymbols::find_sid(klass_name);
}

View File

@ -118,11 +118,12 @@ class Method : public Metadata {
#endif
u2 _method_size; // size of this object
u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
u1 _jfr_towrite : 1, // Flags
_force_inline : 1,
_hidden : 1,
_dont_inline : 1,
: 4;
u1 _jfr_towrite : 1, // Flags
_caller_sensitive : 1,
_force_inline : 1,
_hidden : 1,
_dont_inline : 1,
: 3;
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
u2 _number_of_breakpoints; // fullspeed debugging support
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
@ -618,6 +619,9 @@ class Method : public Metadata {
// Reflection support
bool is_overridden_in(Klass* k) const;
// Stack walking support
bool is_ignored_by_security_stack_walk() const;
// JSR 292 support
bool is_method_handle_intrinsic() const; // MethodHandles::is_signature_polymorphic_intrinsic(intrinsic_id)
bool is_compiled_lambda_form() const; // intrinsic_id() == vmIntrinsics::_compiledLambdaForm
@ -705,15 +709,16 @@ class Method : public Metadata {
void init_intrinsic_id(); // updates from _none if a match
static vmSymbols::SID klass_id_for_intrinsics(Klass* holder);
bool jfr_towrite() { return _jfr_towrite; }
void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; }
bool force_inline() { return _force_inline; }
void set_force_inline(bool x) { _force_inline = x; }
bool dont_inline() { return _dont_inline; }
void set_dont_inline(bool x) { _dont_inline = x; }
bool is_hidden() { return _hidden; }
void set_hidden(bool x) { _hidden = x; }
bool jfr_towrite() { return _jfr_towrite; }
void set_jfr_towrite(bool x) { _jfr_towrite = x; }
bool caller_sensitive() { return _caller_sensitive; }
void set_caller_sensitive(bool x) { _caller_sensitive = x; }
bool force_inline() { return _force_inline; }
void set_force_inline(bool x) { _force_inline = x; }
bool dont_inline() { return _dont_inline; }
void set_dont_inline(bool x) { _dont_inline = x; }
bool is_hidden() { return _hidden; }
void set_hidden(bool x) { _hidden = x; }
ConstMethod::MethodType method_type() const {
return _constMethod->method_type();
}

View File

@ -231,7 +231,6 @@ class LibraryCallKit : public GraphKit {
void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark);
bool inline_native_clone(bool is_virtual);
bool inline_native_Reflection_getCallerClass();
bool is_method_invoke_or_aux_frame(JVMState* jvms);
// Helper function for inlining native object hash method
bool inline_native_hashcode(bool is_virtual, bool is_static);
bool inline_native_getClass();
@ -393,7 +392,7 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
case vmIntrinsics::_getCallerClass:
if (!UseNewReflection) return NULL;
if (!InlineReflectionGetCallerClass) return NULL;
if (!JDK_Version::is_gte_jdk14x_version()) return NULL;
if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return NULL;
break;
case vmIntrinsics::_bitCount_i:
@ -3872,13 +3871,13 @@ bool LibraryCallKit::inline_native_getClass() {
}
//-----------------inline_native_Reflection_getCallerClass---------------------
// public static native Class<?> sun.reflect.Reflection.getCallerClass(int realFramesToSkip);
// public static native Class<?> sun.reflect.Reflection.getCallerClass();
//
// In the presence of deep enough inlining, getCallerClass() becomes a no-op.
//
// NOTE that this code must perform the same logic as
// vframeStream::security_get_caller_frame in that it must skip
// Method.invoke() and auxiliary frames.
// NOTE: This code must perform the same logic as JVM_GetCallerClass
// in that it must skip particular security frames and checks for
// caller sensitive methods.
bool LibraryCallKit::inline_native_Reflection_getCallerClass() {
#ifndef PRODUCT
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
@ -3886,35 +3885,6 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() {
}
#endif
Node* caller_depth_node = argument(0);
// The depth value must be a constant in order for the runtime call
// to be eliminated.
const TypeInt* caller_depth_type = _gvn.type(caller_depth_node)->isa_int();
if (caller_depth_type == NULL || !caller_depth_type->is_con()) {
#ifndef PRODUCT
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
tty->print_cr(" Bailing out because caller depth was not a constant");
}
#endif
return false;
}
// Note that the JVM state at this point does not include the
// getCallerClass() frame which we are trying to inline. The
// semantics of getCallerClass(), however, are that the "first"
// frame is the getCallerClass() frame, so we subtract one from the
// requested depth before continuing. We don't inline requests of
// getCallerClass(0).
int caller_depth = caller_depth_type->get_con() - 1;
if (caller_depth < 0) {
#ifndef PRODUCT
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
tty->print_cr(" Bailing out because caller depth was %d", caller_depth);
}
#endif
return false;
}
if (!jvms()->has_method()) {
#ifndef PRODUCT
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
@ -3923,95 +3893,67 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() {
#endif
return false;
}
int _depth = jvms()->depth(); // cache call chain depth
// Walk back up the JVM state to find the caller at the required
// depth. NOTE that this code must perform the same logic as
// vframeStream::security_get_caller_frame in that it must skip
// Method.invoke() and auxiliary frames. Note also that depth is
// 1-based (1 is the bottom of the inlining).
int inlining_depth = _depth;
JVMState* caller_jvms = NULL;
// depth.
JVMState* caller_jvms = jvms();
if (inlining_depth > 0) {
caller_jvms = jvms();
assert(caller_jvms = jvms()->of_depth(inlining_depth), "inlining_depth == our depth");
do {
// The following if-tests should be performed in this order
if (is_method_invoke_or_aux_frame(caller_jvms)) {
// Skip a Method.invoke() or auxiliary frame
} else if (caller_depth > 0) {
// Skip real frame
--caller_depth;
} else {
// We're done: reached desired caller after skipping.
break;
}
caller_jvms = caller_jvms->caller();
--inlining_depth;
} while (inlining_depth > 0);
}
if (inlining_depth == 0) {
// Cf. JVM_GetCallerClass
// NOTE: Start the loop at depth 1 because the current JVM state does
// not include the Reflection.getCallerClass() frame.
for (int n = 1; caller_jvms != NULL; caller_jvms = caller_jvms->caller(), n++) {
ciMethod* m = caller_jvms->method();
switch (n) {
case 0:
fatal("current JVM state does not include the Reflection.getCallerClass frame");
break;
case 1:
// Frame 0 and 1 must be caller sensitive (see JVM_GetCallerClass).
if (!m->caller_sensitive()) {
#ifndef PRODUCT
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
tty->print_cr(" Bailing out because caller depth (%d) exceeded inlining depth (%d)", caller_depth_type->get_con(), _depth);
tty->print_cr(" JVM state at this point:");
for (int i = _depth; i >= 1; i--) {
ciMethod* m = jvms()->of_depth(i)->method();
tty->print_cr(" %d) %s.%s", i, m->holder()->name()->as_utf8(), m->name()->as_utf8());
}
}
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
tty->print_cr(" Bailing out: CallerSensitive annotation expected at frame %d", n);
}
#endif
return false; // Reached end of inlining
return false; // bail-out; let JVM_GetCallerClass do the work
}
break;
default:
if (!m->is_ignored_by_security_stack_walk()) {
// We have reached the desired frame; return the holder class.
// Acquire method holder as java.lang.Class and push as constant.
ciInstanceKlass* caller_klass = caller_jvms->method()->holder();
ciInstance* caller_mirror = caller_klass->java_mirror();
set_result(makecon(TypeInstPtr::make(caller_mirror)));
#ifndef PRODUCT
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
tty->print_cr(" Succeeded: caller = %d) %s.%s, JVMS depth = %d", n, caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), jvms()->depth());
tty->print_cr(" JVM state at this point:");
for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) {
ciMethod* m = jvms()->of_depth(i)->method();
tty->print_cr(" %d) %s.%s", n, m->holder()->name()->as_utf8(), m->name()->as_utf8());
}
}
#endif
return true;
}
break;
}
}
// Acquire method holder as java.lang.Class
ciInstanceKlass* caller_klass = caller_jvms->method()->holder();
ciInstance* caller_mirror = caller_klass->java_mirror();
// Push this as a constant
set_result(makecon(TypeInstPtr::make(caller_mirror)));
#ifndef PRODUCT
if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
tty->print_cr(" Succeeded: caller = %s.%s, caller depth = %d, depth = %d", caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), caller_depth_type->get_con(), _depth);
tty->print_cr(" Bailing out because caller depth exceeded inlining depth = %d", jvms()->depth());
tty->print_cr(" JVM state at this point:");
for (int i = _depth; i >= 1; i--) {
for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) {
ciMethod* m = jvms()->of_depth(i)->method();
tty->print_cr(" %d) %s.%s", i, m->holder()->name()->as_utf8(), m->name()->as_utf8());
tty->print_cr(" %d) %s.%s", n, m->holder()->name()->as_utf8(), m->name()->as_utf8());
}
}
#endif
return true;
}
// Helper routine for above
bool LibraryCallKit::is_method_invoke_or_aux_frame(JVMState* jvms) {
ciMethod* method = jvms->method();
// Is this the Method.invoke method itself?
if (method->intrinsic_id() == vmIntrinsics::_invoke)
return true;
// Is this a helper, defined somewhere underneath MethodAccessorImpl.
ciKlass* k = method->holder();
if (k->is_instance_klass()) {
ciInstanceKlass* ik = k->as_instance_klass();
for (; ik != NULL; ik = ik->super()) {
if (ik->name() == ciSymbol::sun_reflect_MethodAccessorImpl() &&
ik == env()->find_system_klass(ik->name())) {
return true;
}
}
}
else if (method->is_method_handle_intrinsic() ||
method->is_compiled_lambda_form()) {
// This is an internal adapter frame from the MethodHandleCompiler -- skip it
return true;
}
return false;
return false; // bail-out; let JVM_GetCallerClass do the work
}
bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) {

View File

@ -30,6 +30,7 @@
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/bytecode.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/fieldStreams.hpp"
@ -665,8 +666,51 @@ JVM_END
JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
JVMWrapper("JVM_GetCallerClass");
Klass* k = thread->security_get_caller_class(depth);
return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
// Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation.
if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) {
Klass* k = thread->security_get_caller_class(depth);
return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
} else {
// Basic handshaking with Java_sun_reflect_Reflection_getCallerClass
assert(depth == -1, "wrong handshake depth");
}
// Getting the class of the caller frame.
//
// The call stack at this point looks something like this:
//
// [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ]
// [1] [ @CallerSensitive API.method ]
// [.] [ (skipped intermediate frames) ]
// [n] [ caller ]
vframeStream vfst(thread);
// Cf. LibraryCallKit::inline_native_Reflection_getCallerClass
for (int n = 0; !vfst.at_end(); vfst.security_next(), n++) {
Method* m = vfst.method();
assert(m != NULL, "sanity");
switch (n) {
case 0:
// This must only be called from Reflection.getCallerClass
if (m->intrinsic_id() != vmIntrinsics::_getCallerClass) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetCallerClass must only be called from Reflection.getCallerClass");
}
// fall-through
case 1:
// Frame 0 and 1 must be caller sensitive.
if (!m->caller_sensitive()) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), err_msg("CallerSensitive annotation expected at frame %d", n));
}
break;
default:
if (!m->is_ignored_by_security_stack_walk()) {
// We have reached the desired frame; return the holder class.
return (jclass) JNIHandles::make_local(env, m->method_holder()->java_mirror());
}
break;
}
}
return NULL;
JVM_END
@ -3160,11 +3204,24 @@ JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env))
KlassLink* first = NULL;
KlassLink* last = NULL;
int depth = 0;
vframeStream vfst(thread);
for(vframeStream vfst(thread); !vfst.at_end(); vfst.security_get_caller_frame(1)) {
if (SystemDictionary::reflect_CallerSensitive_klass() != NULL) {
// This must only be called from SecurityManager.getClassContext
Method* m = vfst.method();
if (!(m->method_holder() == SystemDictionary::SecurityManager_klass() &&
m->name() == vmSymbols::getClassContext_name() &&
m->signature() == vmSymbols::void_class_array_signature())) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetClassContext must only be called from SecurityManager.getClassContext");
}
}
// Collect method holders
for (; !vfst.at_end(); vfst.security_next()) {
Method* m = vfst.method();
// Native frames are not returned
if (!vfst.method()->is_native()) {
Klass* holder = vfst.method()->method_holder();
if (!m->is_ignored_by_security_stack_walk() && !m->is_native()) {
Klass* holder = m->method_holder();
assert(holder->is_klass(), "just checking");
depth++;
KlassLink* l = new KlassLink(KlassHandle(thread, holder));

View File

@ -105,14 +105,15 @@ void MethodHandles::set_enabled(bool z) {
// import java_lang_invoke_MemberName.*
enum {
IS_METHOD = java_lang_invoke_MemberName::MN_IS_METHOD,
IS_CONSTRUCTOR = java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR,
IS_FIELD = java_lang_invoke_MemberName::MN_IS_FIELD,
IS_TYPE = java_lang_invoke_MemberName::MN_IS_TYPE,
IS_METHOD = java_lang_invoke_MemberName::MN_IS_METHOD,
IS_CONSTRUCTOR = java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR,
IS_FIELD = java_lang_invoke_MemberName::MN_IS_FIELD,
IS_TYPE = java_lang_invoke_MemberName::MN_IS_TYPE,
CALLER_SENSITIVE = java_lang_invoke_MemberName::MN_CALLER_SENSITIVE,
REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT,
REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK,
SEARCH_SUPERCLASSES = java_lang_invoke_MemberName::MN_SEARCH_SUPERCLASSES,
SEARCH_INTERFACES = java_lang_invoke_MemberName::MN_SEARCH_INTERFACES,
SEARCH_SUPERCLASSES = java_lang_invoke_MemberName::MN_SEARCH_SUPERCLASSES,
SEARCH_INTERFACES = java_lang_invoke_MemberName::MN_SEARCH_INTERFACES,
ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE
};
@ -207,10 +208,15 @@ oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_disp
vmindex = m->vtable_index();
}
java_lang_invoke_MemberName::set_flags(mname_oop, flags);
// @CallerSensitive annotation detected
if (m->caller_sensitive()) {
flags |= CALLER_SENSITIVE;
}
java_lang_invoke_MemberName::set_flags( mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, m);
java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); // vtable/itable index
java_lang_invoke_MemberName::set_clazz(mname_oop, receiver_limit->java_mirror());
java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index
java_lang_invoke_MemberName::set_clazz( mname_oop, receiver_limit->java_mirror());
// Note: name and type can be lazily computed by resolve_MemberName,
// if Java code needs them as resolved String and MethodType objects.
// The clazz must be eagerly stored, because it provides a GC
@ -940,6 +946,7 @@ JVM_END
template(java_lang_invoke_MemberName,MN_IS_CONSTRUCTOR) \
template(java_lang_invoke_MemberName,MN_IS_FIELD) \
template(java_lang_invoke_MemberName,MN_IS_TYPE) \
template(java_lang_invoke_MemberName,MN_CALLER_SENSITIVE) \
template(java_lang_invoke_MemberName,MN_SEARCH_SUPERCLASSES) \
template(java_lang_invoke_MemberName,MN_SEARCH_INTERFACES) \
template(java_lang_invoke_MemberName,MN_REFERENCE_KIND_SHIFT) \

View File

@ -868,7 +868,7 @@ static inline void throw_new(JNIEnv *env, const char *ename) {
env->ThrowNew(cls, msg);
}
static jclass Unsafe_DefineClass(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
{
// Code lifted from JDK 1.3 ClassLoader.c
@ -939,6 +939,15 @@ static jclass Unsafe_DefineClass(JNIEnv *env, jstring name, jbyteArray data, int
}
UNSAFE_ENTRY(jclass, Unsafe_DefineClass(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd))
UnsafeWrapper("Unsafe_DefineClass");
{
ThreadToNativeFromVM ttnfv(thread);
return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd);
}
UNSAFE_END
UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length))
UnsafeWrapper("Unsafe_DefineClass");
{
@ -949,20 +958,11 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring na
jobject loader = (caller == NULL) ? NULL : JVM_GetClassLoader(env, caller);
jobject pd = (caller == NULL) ? NULL : JVM_GetProtectionDomain(env, caller);
return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd);
}
UNSAFE_END
UNSAFE_ENTRY(jclass, Unsafe_DefineClass1(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd))
UnsafeWrapper("Unsafe_DefineClass");
{
ThreadToNativeFromVM ttnfv(thread);
return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
}
UNSAFE_END
#define DAC_Args CLS"[B["OBJ
// define a class but do not make it known to the class loader or system dictionary
// - host_class: supplies context for linkage, access control, protection domain, and class loader
@ -1323,7 +1323,7 @@ UNSAFE_END
#define THR LANG"Throwable;"
#define DC0_Args LANG"String;[BII"
#define DC1_Args DC0_Args LANG"ClassLoader;" "Ljava/security/ProtectionDomain;"
#define DC_Args DC0_Args LANG"ClassLoader;" "Ljava/security/ProtectionDomain;"
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
@ -1352,10 +1352,8 @@ UNSAFE_END
// %%% These are temporarily supported until the SDK sources
// contain the necessarily updated Unsafe.java.
// These are the methods for 1.4.0
static JNINativeMethod methods_140[] = {
{CC"getObject", CC"("OBJ"I)"OBJ"", FN_PTR(Unsafe_GetObject140)},
{CC"putObject", CC"("OBJ"I"OBJ")V", FN_PTR(Unsafe_SetObject140)},
@ -1381,12 +1379,10 @@ static JNINativeMethod methods_140[] = {
{CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
{CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
// {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
// {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
{CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
{CC"fieldOffset", CC"("FLD")I", FN_PTR(Unsafe_FieldOffset)}, //deprecated
{CC"staticFieldBase", CC"("CLS")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromClass)}, //deprecated
{CC"fieldOffset", CC"("FLD")I", FN_PTR(Unsafe_FieldOffset)},
{CC"staticFieldBase", CC"("CLS")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromClass)},
{CC"ensureClassInitialized",CC"("CLS")V", FN_PTR(Unsafe_EnsureClassInitialized)},
{CC"arrayBaseOffset", CC"("CLS")I", FN_PTR(Unsafe_ArrayBaseOffset)},
{CC"arrayIndexScale", CC"("CLS")I", FN_PTR(Unsafe_ArrayIndexScale)},
@ -1394,16 +1390,15 @@ static JNINativeMethod methods_140[] = {
{CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
{CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}
};
// These are the old methods prior to the JSR 166 changes in 1.5.0
// These are the methods prior to the JSR 166 changes in 1.5.0
static JNINativeMethod methods_141[] = {
{CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)},
{CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)},
@ -1429,8 +1424,6 @@ static JNINativeMethod methods_141[] = {
{CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
{CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
// {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
// {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
{CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
{CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)},
@ -1443,7 +1436,7 @@ static JNINativeMethod methods_141[] = {
{CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
{CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
@ -1451,9 +1444,8 @@ static JNINativeMethod methods_141[] = {
};
// These are the old methods prior to the JSR 166 changes in 1.6.0
// These are the methods prior to the JSR 166 changes in 1.6.0
static JNINativeMethod methods_15[] = {
{CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)},
{CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)},
{CC"getObjectVolatile",CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObjectVolatile)},
@ -1482,8 +1474,6 @@ static JNINativeMethod methods_15[] = {
{CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
{CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
// {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
// {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
{CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
{CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)},
@ -1496,7 +1486,7 @@ static JNINativeMethod methods_15[] = {
{CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
{CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
@ -1509,15 +1499,13 @@ static JNINativeMethod methods_15[] = {
};
// These are the correct methods, moving forward:
static JNINativeMethod methods[] = {
// These are the methods for 1.6.0 and 1.7.0
static JNINativeMethod methods_16[] = {
{CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)},
{CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)},
{CC"getObjectVolatile",CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObjectVolatile)},
{CC"putObjectVolatile",CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObjectVolatile)},
DECLARE_GETSETOOP(Boolean, Z),
DECLARE_GETSETOOP(Byte, B),
DECLARE_GETSETOOP(Short, S),
@ -1540,8 +1528,6 @@ static JNINativeMethod methods[] = {
{CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
{CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
// {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
// {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
{CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
{CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)},
@ -1554,7 +1540,7 @@ static JNINativeMethod methods[] = {
{CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
{CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
@ -1566,23 +1552,68 @@ static JNINativeMethod methods[] = {
{CC"putOrderedObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetOrderedObject)},
{CC"putOrderedInt", CC"("OBJ"JI)V", FN_PTR(Unsafe_SetOrderedInt)},
{CC"putOrderedLong", CC"("OBJ"JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
{CC"loadFence", CC"()V", FN_PTR(Unsafe_LoadFence)},
{CC"storeFence", CC"()V", FN_PTR(Unsafe_StoreFence)},
{CC"fullFence", CC"()V", FN_PTR(Unsafe_FullFence)},
{CC"park", CC"(ZJ)V", FN_PTR(Unsafe_Park)},
{CC"unpark", CC"("OBJ")V", FN_PTR(Unsafe_Unpark)}
};
// {CC"getLoadAverage", CC"([DI)I", FN_PTR(Unsafe_Loadavg)},
// These are the methods for 1.8.0
static JNINativeMethod methods_18[] = {
{CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)},
{CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)},
{CC"getObjectVolatile",CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObjectVolatile)},
{CC"putObjectVolatile",CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObjectVolatile)},
// {CC"prefetchRead", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchRead)},
// {CC"prefetchWrite", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchWrite)}
// {CC"prefetchReadStatic", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchRead)},
// {CC"prefetchWriteStatic",CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchWrite)}
DECLARE_GETSETOOP(Boolean, Z),
DECLARE_GETSETOOP(Byte, B),
DECLARE_GETSETOOP(Short, S),
DECLARE_GETSETOOP(Char, C),
DECLARE_GETSETOOP(Int, I),
DECLARE_GETSETOOP(Long, J),
DECLARE_GETSETOOP(Float, F),
DECLARE_GETSETOOP(Double, D),
DECLARE_GETSETNATIVE(Byte, B),
DECLARE_GETSETNATIVE(Short, S),
DECLARE_GETSETNATIVE(Char, C),
DECLARE_GETSETNATIVE(Int, I),
DECLARE_GETSETNATIVE(Long, J),
DECLARE_GETSETNATIVE(Float, F),
DECLARE_GETSETNATIVE(Double, D),
{CC"getAddress", CC"("ADR")"ADR, FN_PTR(Unsafe_GetNativeAddress)},
{CC"putAddress", CC"("ADR""ADR")V", FN_PTR(Unsafe_SetNativeAddress)},
{CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
{CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
{CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
{CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)},
{CC"staticFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_StaticFieldOffset)},
{CC"staticFieldBase", CC"("FLD")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)},
{CC"ensureClassInitialized",CC"("CLS")V", FN_PTR(Unsafe_EnsureClassInitialized)},
{CC"arrayBaseOffset", CC"("CLS")I", FN_PTR(Unsafe_ArrayBaseOffset)},
{CC"arrayIndexScale", CC"("CLS")I", FN_PTR(Unsafe_ArrayIndexScale)},
{CC"addressSize", CC"()I", FN_PTR(Unsafe_AddressSize)},
{CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
{CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"tryMonitorEnter", CC"("OBJ")Z", FN_PTR(Unsafe_TryMonitorEnter)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
{CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
{CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)},
{CC"putOrderedObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetOrderedObject)},
{CC"putOrderedInt", CC"("OBJ"JI)V", FN_PTR(Unsafe_SetOrderedInt)},
{CC"putOrderedLong", CC"("OBJ"JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
{CC"park", CC"(ZJ)V", FN_PTR(Unsafe_Park)},
{CC"unpark", CC"("OBJ")V", FN_PTR(Unsafe_Unpark)}
};
JNINativeMethod loadavg_method[] = {
{CC"getLoadAverage", CC"([DI)I", FN_PTR(Unsafe_Loadavg)}
{CC"getLoadAverage", CC"([DI)I", FN_PTR(Unsafe_Loadavg)}
};
JNINativeMethod prefetch_methods[] = {
@ -1592,7 +1623,7 @@ JNINativeMethod prefetch_methods[] = {
{CC"prefetchWriteStatic",CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchWrite)}
};
JNINativeMethod memcopy_methods[] = {
JNINativeMethod memcopy_methods_17[] = {
{CC"copyMemory", CC"("OBJ"J"OBJ"JJ)V", FN_PTR(Unsafe_CopyMemory2)},
{CC"setMemory", CC"("OBJ"JJB)V", FN_PTR(Unsafe_SetMemory2)}
};
@ -1610,6 +1641,12 @@ JNINativeMethod lform_methods[] = {
{CC"shouldBeInitialized",CC"("CLS")Z", FN_PTR(Unsafe_ShouldBeInitialized)},
};
JNINativeMethod fence_methods[] = {
{CC"loadFence", CC"()V", FN_PTR(Unsafe_LoadFence)},
{CC"storeFence", CC"()V", FN_PTR(Unsafe_StoreFence)},
{CC"fullFence", CC"()V", FN_PTR(Unsafe_FullFence)},
};
#undef CC
#undef FN_PTR
@ -1622,12 +1659,32 @@ JNINativeMethod lform_methods[] = {
#undef MTH
#undef THR
#undef DC0_Args
#undef DC1_Args
#undef DC_Args
#undef DECLARE_GETSETOOP
#undef DECLARE_GETSETNATIVE
/**
* Helper method to register native methods.
*/
static bool register_natives(const char* message, JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) {
int status = env->RegisterNatives(clazz, methods, nMethods);
if (status < 0 || env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Unsafe: failed registering %s", message);
}
env->ExceptionClear();
return false;
} else {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Unsafe: successfully registered %s", message);
}
return true;
}
}
// This one function is exported, used by NativeLookup.
// The Unsafe_xxx functions above are called only from the interpreter.
// The optimizer looks at names and signatures to recognize
@ -1637,83 +1694,57 @@ JVM_ENTRY(void, JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls))
UnsafeWrapper("JVM_RegisterUnsafeMethods");
{
ThreadToNativeFromVM ttnfv(thread);
// Unsafe methods
{
env->RegisterNatives(unsafecls, loadavg_method, sizeof(loadavg_method)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.6 Unsafe.loadavg not found.");
}
env->ExceptionClear();
}
}
{
env->RegisterNatives(unsafecls, prefetch_methods, sizeof(prefetch_methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.6 Unsafe.prefetchRead/Write not found.");
}
env->ExceptionClear();
}
}
{
env->RegisterNatives(unsafecls, memcopy_methods, sizeof(memcopy_methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.7 Unsafe.copyMemory not found.");
}
env->ExceptionClear();
env->RegisterNatives(unsafecls, memcopy_methods_15, sizeof(memcopy_methods_15)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.5 Unsafe.copyMemory not found.");
}
env->ExceptionClear();
}
bool success = false;
// We need to register the 1.6 methods first because the 1.8 methods would register fine on 1.7 and 1.6
if (!success) {
success = register_natives("1.6 methods", env, unsafecls, methods_16, sizeof(methods_16)/sizeof(JNINativeMethod));
}
if (!success) {
success = register_natives("1.8 methods", env, unsafecls, methods_18, sizeof(methods_18)/sizeof(JNINativeMethod));
}
if (!success) {
success = register_natives("1.5 methods", env, unsafecls, methods_15, sizeof(methods_15)/sizeof(JNINativeMethod));
}
if (!success) {
success = register_natives("1.4.1 methods", env, unsafecls, methods_141, sizeof(methods_141)/sizeof(JNINativeMethod));
}
if (!success) {
success = register_natives("1.4.0 methods", env, unsafecls, methods_140, sizeof(methods_140)/sizeof(JNINativeMethod));
}
guarantee(success, "register unsafe natives");
}
// Unsafe.getLoadAverage
register_natives("1.6 loadavg method", env, unsafecls, loadavg_method, sizeof(loadavg_method)/sizeof(JNINativeMethod));
// Prefetch methods
register_natives("1.6 prefetch methods", env, unsafecls, prefetch_methods, sizeof(prefetch_methods)/sizeof(JNINativeMethod));
// Memory copy methods
{
bool success = false;
if (!success) {
success = register_natives("1.7 memory copy methods", env, unsafecls, memcopy_methods_17, sizeof(memcopy_methods_17)/sizeof(JNINativeMethod));
}
if (!success) {
success = register_natives("1.5 memory copy methods", env, unsafecls, memcopy_methods_15, sizeof(memcopy_methods_15)/sizeof(JNINativeMethod));
}
}
// Unsafe.defineAnonymousClass
if (EnableInvokeDynamic) {
env->RegisterNatives(unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.7 Unsafe.defineClass (anonymous version) not found.");
}
env->ExceptionClear();
}
register_natives("1.7 define anonymous class method", env, unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod));
}
// Unsafe.shouldBeInitialized
if (EnableInvokeDynamic) {
env->RegisterNatives(unsafecls, lform_methods, sizeof(lform_methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.7 LambdaForm support in Unsafe not found.");
}
env->ExceptionClear();
}
register_natives("1.7 LambdaForm support", env, unsafecls, lform_methods, sizeof(lform_methods)/sizeof(JNINativeMethod));
}
int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.6 version of Unsafe not found.");
}
env->ExceptionClear();
// %%% For now, be backward compatible with an older class:
status = env->RegisterNatives(unsafecls, methods_15, sizeof(methods_15)/sizeof(JNINativeMethod));
}
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.5 version of Unsafe not found.");
}
env->ExceptionClear();
// %%% For now, be backward compatible with an older class:
status = env->RegisterNatives(unsafecls, methods_141, sizeof(methods_141)/sizeof(JNINativeMethod));
}
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.4.1 version of Unsafe not found.");
}
env->ExceptionClear();
// %%% For now, be backward compatible with an older class:
status = env->RegisterNatives(unsafecls, methods_140, sizeof(methods_140)/sizeof(JNINativeMethod));
}
guarantee(status == 0, "register unsafe natives");
// Fence methods
register_natives("1.8 fence methods", env, unsafecls, fence_methods, sizeof(fence_methods)/sizeof(JNINativeMethod));
}
JVM_END

View File

@ -391,40 +391,27 @@ vframeStream::vframeStream(JavaThread* thread, frame top_frame,
// Step back n frames, skip any pseudo frames in between.
// This function is used in Class.forName, Class.newInstance, Method.Invoke,
// AccessController.doPrivileged.
//
// NOTE that in JDK 1.4 this has been exposed to Java as
// sun.reflect.Reflection.getCallerClass(), which can be inlined.
// Inlined versions must match this routine's logic.
// Native method prefixing logic does not need to match since
// the method names don't match and inlining will not occur.
// See, for example,
// Parse::inline_native_Reflection_getCallerClass in
// opto/library_call.cpp.
void vframeStreamCommon::security_get_caller_frame(int depth) {
bool use_new_reflection = JDK_Version::is_gte_jdk14x_version() && UseNewReflection;
while (!at_end()) {
if (Universe::reflect_invoke_cache()->is_same_method(method())) {
// This is Method.invoke() -- skip it
} else if (use_new_reflection &&
method()->method_holder()
->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) {
// This is an auxilary frame -- skip it
} else if (method()->is_method_handle_intrinsic() ||
method()->is_compiled_lambda_form()) {
// This is an internal adapter frame for method handles -- skip it
} else {
// This is non-excluded frame, we need to count it against the depth
if (depth-- <= 0) {
// we have reached the desired depth, we are done
break;
assert(depth >= 0, err_msg("invalid depth: %d", depth));
for (int n = 0; !at_end(); security_next()) {
if (!method()->is_ignored_by_security_stack_walk()) {
if (n == depth) {
// We have reached the desired depth; return.
return;
}
n++; // this is a non-skipped frame; count it against the depth
}
if (method()->is_prefixed_native()) {
skip_prefixed_method_and_wrappers();
} else {
next();
}
}
// NOTE: At this point there were not enough frames on the stack
// to walk to depth. Callers of this method have to check for at_end.
}
void vframeStreamCommon::security_next() {
if (method()->is_prefixed_native()) {
skip_prefixed_method_and_wrappers(); // calls next()
} else {
next();
}
}

View File

@ -336,6 +336,7 @@ class vframeStreamCommon : StackObj {
_frame = _frame.sender(&_reg_map);
} while (!fill_from_frame());
}
void security_next();
bool at_end() const { return _mode == at_end_mode; }