--- old/src/share/vm/prims/jni.cpp 2015-06-27 04:11:13.000000000 +0300 +++ new/src/share/vm/prims/jni.cpp 2015-06-27 04:11:13.000000000 +0300 @@ -31,6 +31,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" +#include "code/dependencies.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "interpreter/linkResolver.hpp" #include "memory/allocation.hpp" @@ -60,6 +61,7 @@ #include "runtime/fieldDescriptor.hpp" #include "runtime/fprofiler.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -168,7 +170,7 @@ // out-of-line helpers for class jfieldIDWorkaround: bool jfieldIDWorkaround::is_valid_jfieldID(Klass* k, jfieldID id) { - if (jfieldIDWorkaround::is_instance_jfieldID(k, id)) { + if (jfieldIDWorkaround::is_instance_jfieldID(id)) { uintptr_t as_uint = (uintptr_t) id; intptr_t offset = raw_instance_offset(id); if (is_checked_jfieldID(id)) { @@ -229,7 +231,7 @@ } void jfieldIDWorkaround::verify_instance_jfieldID(Klass* k, jfieldID id) { - guarantee(jfieldIDWorkaround::is_instance_jfieldID(k, id), "must be an instance field" ); + guarantee(jfieldIDWorkaround::is_instance_jfieldID(id), "must be an instance field" ); uintptr_t as_uint = (uintptr_t) id; intptr_t offset = raw_instance_offset(id); if (VerifyJNIFields) { @@ -506,7 +508,8 @@ // It may also have hash bits for k, if VerifyJNIFields is turned on. intptr_t offset = InstanceKlass::cast(k1())->field_offset( slot ); assert(InstanceKlass::cast(k1())->contains_field_offset(offset), "stay within object"); - ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset); + bool is_final = (modifiers & JVM_ACC_FINAL) != 0; + ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset, is_final); return ret; JNI_END @@ -2041,7 +2044,7 @@ // 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. - ret = jfieldIDWorkaround::to_instance_jfieldID(k(), fd.offset()); + ret = jfieldIDWorkaround::to_instance_jfieldID(k(), fd.offset(), fd.access_flags().is_final()); return ret; JNI_END @@ -2161,9 +2164,26 @@ return (address)jni_GetDoubleField; } +static void check_final_field(jobject obj, jfieldID fieldID, TRAPS) { + if (TrustFinalNonStaticFields && + jfieldIDWorkaround::is_final_jfieldID(fieldID) && + jfieldIDWorkaround::is_instance_jfieldID(fieldID)) { + ResetNoHandleMark rm; + HandleMark hm; + Handle recv(THREAD, JNIHandles::resolve(obj)); + if (!recv.is_null()) { + instanceKlassHandle ctxk(THREAD, InstanceKlass::cast(recv->klass())); + int offset = (int)jfieldIDWorkaround::from_instance_jfieldID(ctxk(), fieldID); + ConstantFieldDepChange changes(recv, offset); + Dependencies::invalidate_dependent_nmethods(ctxk, changes, THREAD); + } + } +} + JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)) JNIWrapper("SetObjectField"); HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value); + check_final_field(obj, fieldID, thread); oop o = JNIHandles::resolve_non_null(obj); Klass* k = o->klass(); int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); @@ -2188,6 +2208,7 @@ \ EntryProbe; \ \ + check_final_field(obj, fieldID, thread); \ oop o = JNIHandles::resolve_non_null(obj); \ Klass* k = o->klass(); \ int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \