/* * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This 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. *
*/
staticinlinevoid* addr_from_java(jlong addr) { // This assert fails in a variety of ways on 32-bit systems. // It is impossible to predict whether native code that converts // pointers to longs will sign-extend or zero-extend the addresses. //assert(addr == (uintptr_t)addr, "must not be odd high bits"); return (void*)(uintptr_t)addr;
}
staticinline jlong addr_to_java(void* p) {
assert(p == (void*)(uintptr_t)p, "must not be odd high bits"); return (uintptr_t)p;
}
// Note: The VM's obj_field and related accessors use byte-scaled // ("unscaled") offsets, just as the unsafe methods do.
// However, the method Unsafe.fieldOffset explicitly declines to // guarantee this. The field offset values manipulated by the Java user // through the Unsafe API are opaque cookies that just happen to be byte // offsets. We represent this state of affairs by passing the cookies // through conversion functions when going between the VM and the Unsafe API. // The conversion functions just happen to be no-ops at present.
// Externally callable versions: // (Use these in compiler intrinsics which emulate unsafe primitives.)
jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) { return field_offset;
}
jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { return byte_offset;
}
///// Data read/writes on the Java heap and in native (off-heap) memory
/** * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
*/ class GuardUnsafeAccess {
JavaThread* _thread;
public:
GuardUnsafeAccess(JavaThread* thread) : _thread(thread) { // native/off-heap access which may raise SIGBUS if accessing // memory mapped file data in a region of the file which has // been truncated and is now invalid.
_thread->set_doing_unsafe_access(true);
}
/** * Helper class for accessing memory. * * Normalizes values and wraps accesses in * JavaThread::doing_unsafe_access() if needed.
*/ template <typename T> class MemoryAccess : StackObj {
JavaThread* _thread;
oop _obj;
ptrdiff_t _offset;
// Resolves and returns the address of the memory access. // This raw memory access may fault, so we make sure it happens within the // guarded scope by making the access volatile at least. Since the store // of Thread::set_doing_unsafe_access() is also volatile, these accesses // can not be reordered by the compiler. Therefore, if the access triggers // a fault, we will know that Thread::doing_unsafe_access() returns true. volatile T* addr() { void* addr = index_oop_from_field_offset_long(_obj, _offset); returnstatic_cast<volatile T*>(addr);
}
template <typename U>
U normalize_for_write(U x) { return x;
}
jboolean normalize_for_write(jboolean x) { return x & 1;
}
template <typename U>
U normalize_for_read(U x) { return x;
}
jboolean normalize_for_read(jboolean x) { return x != 0;
}
// These functions allow a null base pointer with an arbitrary address. // But if the base pointer is non-null, the offset should make some sense. // That is, it should be in the range [0, MAX_OBJECT_SIZE].
UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
oop p = JNIHandles::resolve(obj);
assert_field_offset_sane(p, offset);
oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); return JNIHandles::make_local(THREAD, v);
} UNSAFE_END
// This function is a leaf since if the source and destination are both in native memory // the copy may potentially be very large, and we don't want to disable GC if we can avoid it. // If either source or destination (or both) are on the heap, the function will enter VM using // JVM_ENTRY_FROM_LEAF
UNSAFE_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) {
size_t sz = (size_t)size;
size_t esz = (size_t)elemSize;
if (srcObj == NULL && dstObj == NULL) { // Both src & dst are in native memory
address src = (address)srcOffset;
address dst = (address)dstOffset;
{
JavaThread* thread = JavaThread::thread_from_jni_environment(env);
GuardUnsafeAccess guard(thread);
Copy::conjoint_swap(src, dst, sz, esz);
}
} else { // At least one of src/dst are on heap, transition to VM to access raw pointers
UNSAFE_LEAF (void, Unsafe_WriteBackPreSync0(JNIEnv *env, jobject unsafe)) {
assert(VM_Version::supports_data_cache_line_flush(), "should not get here"); #ifdef ASSERT if (TraceMemoryWriteback) {
tty->print_cr("Unsafe: writeback pre-sync");
} #endif
doWriteBackSync0(true);
} UNSAFE_END
UNSAFE_LEAF (void, Unsafe_WriteBackPostSync0(JNIEnv *env, jobject unsafe)) {
assert(VM_Version::supports_data_cache_line_flush(), "should not get here"); #ifdef ASSERT if (TraceMemoryWriteback) {
tty->print_cr("Unsafe: writeback pre-sync");
} #endif
doWriteBackSync0(false);
} UNSAFE_END
////// Random queries
static jlong find_field_offset(jclass clazz, jstring name, TRAPS) {
assert(clazz != NULL, "clazz must not be NULL");
assert(name != NULL, "name must not be NULL");
UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBase0(JNIEnv *env, jobject unsafe, jobject field)) {
assert(field != NULL, "field must not be NULL");
// Note: In this VM implementation, a field address is always a short // offset from the base of a klass metaobject. Thus, the full dynamic // range of the return type is never used. However, some implementations // might put the static field inside an array shared by many classes, // or even at a fixed address, in which case the address could be quite // large. In that last case, this function would return NULL, since // the address would operate alone, without any base pointer.
UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) { int base = 0, scale = 0;
getBaseAndScale(base, scale, clazz, CHECK_0);
// This VM packs both fields and array elements down to the byte. // But watch out: If this changes, so that array references for // a given primitive type (say, T_BOOLEAN) use different memory units // than fields, this method MUST return zero for such arrays. // For example, the VM used to store sub-word sized fields in full // words in the object layout, so that accessors like getByte(Object,int) // did not really do what one might expect for arrays. Therefore, // this function used to report a zero scale factor, so that the user // would know not to attempt to access sub-word array elements. // // Code for unpacked fields: // if (scale < wordSize) return 0;
// The following allows for a pretty general fieldOffset cookie scheme, // but requires it to be linear in byte offset. return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
} UNSAFE_END
staticinlinevoid throw_new(JNIEnv *env, constchar *ename) {
jclass cls = env->FindClass(ename); if (env->ExceptionCheck()) {
env->ExceptionClear();
tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", ename); return;
}
env->ThrowNew(cls, NULL);
}
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
typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(loadavg));
assert(a->is_typeArray(), "must be type array");
ret = os::loadavg(la, nelem); if (ret == -1) { return -1;
}
// if successful, ret is the number of samples actually retrieved.
assert(ret >= 0 && ret <= max_nelem, "Unexpected loadavg return value"); switch(ret) { case 3: a->double_at_put(2, (jdouble)la[2]); // fall through case 2: a->double_at_put(1, (jdouble)la[1]); // fall through case 1: a->double_at_put(0, (jdouble)la[0]); break;
}
return ret;
} UNSAFE_END
/// JVM_RegisterUnsafeMethods
#define ADR "J"
#define LANG "Ljava/lang/"
#define OBJ LANG "Object;" #define CLS LANG "Class;" #define FLD LANG "reflect/Field;" #define THR LANG "Throwable;"
#define DC_Args LANG "String;[BII" LANG "ClassLoader;""Ljava/security/ProtectionDomain;" #define DAC_Args CLS "[B[" OBJ
#define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
#define DECLARE_GETPUTOOP(Type, Desc) \
{CC "get"#Type, CC "(" OBJ "J)"#Desc, FN_PTR(Unsafe_Get##Type)}, \
{CC "put"#Type, CC "(" OBJ "J"#Desc")V", FN_PTR(Unsafe_Put##Type)}, \
{CC "get"#Type"Volatile", CC "(" OBJ "J)"#Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \
{CC "put"#Type"Volatile", CC "(" OBJ "J"#Desc")V", FN_PTR(Unsafe_Put##Type##Volatile)}
static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
{CC "getReference", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetReference)},
{CC "putReference", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReference)},
{CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ, FN_PTR(Unsafe_GetReferenceVolatile)},
{CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReferenceVolatile)},
{CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)},
// This 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 // individual functions.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.