< prev index next > src/hotspot/share/prims/jvm.cpp
Print this page
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
#include "oops/constantPool.hpp"
#include "oops/fieldStreams.inline.hpp"
+ #include "oops/flatArrayKlass.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.hpp"
#include "oops/recordComponent.hpp"
#include "oops/objArrayKlass.hpp"
const char* temp_dir = os::get_temp_directory();
Handle h = java_lang_String::create_from_platform_dependent_str(temp_dir, CHECK_NULL);
return (jstring) JNIHandles::make_local(THREAD, h());
JVM_END
+ JVM_ENTRY(jarray, JVM_NewNullRestrictedArray(JNIEnv *env, jclass elmClass, jint len))
+ if (len < 0) {
+ THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Array length is negative");
+ }
+ oop mirror = JNIHandles::resolve_non_null(elmClass);
+ Klass* klass = java_lang_Class::as_Klass(mirror);
+ klass->initialize(CHECK_NULL);
+ if (klass->is_identity_class()) {
+ THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Element class is not a value class");
+ }
+ if (klass->is_abstract()) {
+ THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Element class is abstract");
+ }
+ InlineKlass* vk = InlineKlass::cast(klass);
+ if (!vk->is_implicitly_constructible()) {
+ THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Element class is not implicitly constructible");
+ }
+ oop array = oopFactory::new_valueArray(vk, len, CHECK_NULL);
+ return (jarray) JNIHandles::make_local(THREAD, array);
+ JVM_END
+
+
+ JVM_ENTRY(jboolean, JVM_IsNullRestrictedArray(JNIEnv *env, jobject obj))
+ arrayOop oop = arrayOop(JNIHandles::resolve_non_null(obj));
+ return oop->is_null_free_array();
+ JVM_END
// java.lang.Runtime /////////////////////////////////////////////////////////////////////////
extern volatile jint vm_created;
// java.lang.Object ///////////////////////////////////////////////
JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
// as implemented in the classic virtual machine; return 0 if object is null
! return handle == nullptr ? 0 :
! checked_cast<jint>(ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)));
JVM_END
JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
// java.lang.Object ///////////////////////////////////////////////
JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
// as implemented in the classic virtual machine; return 0 if object is null
! if (handle == nullptr) {
! return 0;
+ }
+ oop obj = JNIHandles::resolve_non_null(handle);
+ if (EnableValhalla && obj->klass()->is_inline_klass()) {
+ JavaValue result(T_INT);
+ JavaCallArguments args;
+ Handle ho(THREAD, obj);
+ args.push_oop(ho);
+ methodHandle method(THREAD, Universe::value_object_hash_code_method());
+ JavaCalls::call(&result, method, &args, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ if (!PENDING_EXCEPTION->is_a(vmClasses::Error_klass())) {
+ Handle e(THREAD, PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+ THROW_MSG_CAUSE_(vmSymbols::java_lang_InternalError(), "Internal error in hashCode", e, false);
+ }
+ }
+ return result.get_jint();
+ } else {
+ return checked_cast<jint>(ObjectSynchronizer::FastHashCode(THREAD, obj));
+ }
JVM_END
JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
InstanceKlass::cast(klass)->reference_type() != REF_NONE)) {
ResourceMark rm(THREAD);
THROW_MSG_NULL(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name());
}
+ if (klass->is_inline_klass()) {
+ // Value instances have no identity, so return the current instance instead of allocating a new one
+ // Value classes cannot have finalizers, so the method can return immediately
+ return JNIHandles::make_local(THREAD, obj());
+ }
+
// Make shallow object copy
const size_t size = obj->size();
oop new_obj_oop = nullptr;
if (obj->is_array()) {
const int length = ((arrayOop)obj())->length();
Klass* klass = java_lang_Class::as_Klass(mirror);
// Figure size of result array
int size;
if (klass->is_instance_klass()) {
! size = InstanceKlass::cast(klass)->local_interfaces()->length();
} else {
! assert(klass->is_objArray_klass() || klass->is_typeArray_klass(), "Illegal mirror klass");
size = 2;
}
// Allocate result array
objArrayOop r = oopFactory::new_objArray(vmClasses::Class_klass(), size, CHECK_NULL);
objArrayHandle result (THREAD, r);
// Fill in result
if (klass->is_instance_klass()) {
// Regular instance klass, fill in all local interfaces
for (int index = 0; index < size; index++) {
! Klass* k = InstanceKlass::cast(klass)->local_interfaces()->at(index);
result->obj_at_put(index, k->java_mirror());
}
} else {
// All arrays implement java.lang.Cloneable and java.io.Serializable
result->obj_at_put(0, vmClasses::Cloneable_klass()->java_mirror());
Klass* klass = java_lang_Class::as_Klass(mirror);
// Figure size of result array
int size;
if (klass->is_instance_klass()) {
! InstanceKlass* ik = InstanceKlass::cast(klass);
+ size = ik->local_interfaces()->length();
} else {
! assert(klass->is_objArray_klass() || klass->is_typeArray_klass() || klass->is_flatArray_klass(), "Illegal mirror klass");
size = 2;
}
// Allocate result array
objArrayOop r = oopFactory::new_objArray(vmClasses::Class_klass(), size, CHECK_NULL);
objArrayHandle result (THREAD, r);
// Fill in result
if (klass->is_instance_klass()) {
// Regular instance klass, fill in all local interfaces
for (int index = 0; index < size; index++) {
! InstanceKlass* ik = InstanceKlass::cast(klass);
+ Klass* k = ik->local_interfaces()->at(index);
result->obj_at_put(index, k->java_mirror());
}
} else {
// All arrays implement java.lang.Cloneable and java.io.Serializable
result->obj_at_put(0, vmClasses::Cloneable_klass()->java_mirror());
}
Klass* k = java_lang_Class::as_Klass(mirror);
return k->is_hidden();
JVM_END
+ JVM_ENTRY(jboolean, JVM_IsIdentityClass(JNIEnv *env, jclass cls))
+ oop mirror = JNIHandles::resolve_non_null(cls);
+ if (java_lang_Class::is_primitive(mirror)) {
+ return JNI_FALSE;
+ }
+ Klass* k = java_lang_Class::as_Klass(mirror);
+ if (EnableValhalla) {
+ return k->is_array_klass() || k->is_identity_class();
+ } else {
+ return k->is_interface() ? JNI_FALSE : JNI_TRUE;
+ }
+ JVM_END
+
+ JVM_ENTRY(jboolean, JVM_IsImplicitlyConstructibleClass(JNIEnv *env, jclass cls))
+ oop mirror = JNIHandles::resolve_non_null(cls);
+ InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
+ return ik->is_implicitly_constructible();
+ JVM_END
+
JVM_ENTRY(jobject, JVM_GetProtectionDomain(JNIEnv *env, jclass cls))
oop mirror = JNIHandles::resolve_non_null(cls);
if (mirror == nullptr) {
THROW_(vmSymbols::java_lang_NullPointerException(), nullptr);
int num_methods = 0;
// Select methods matching the criteria.
for (int i = 0; i < methods_length; i++) {
Method* method = methods->at(i);
! if (want_constructor && !method->is_object_initializer()) {
continue;
}
if (!want_constructor &&
! (method->is_object_initializer() || method->is_static_initializer() ||
method->is_overpass())) {
continue;
}
if (publicOnly && !method->is_public()) {
continue;
int num_methods = 0;
// Select methods matching the criteria.
for (int i = 0; i < methods_length; i++) {
Method* method = methods->at(i);
! if (want_constructor && !method->is_object_constructor()) {
continue;
}
if (!want_constructor &&
! (method->is_object_constructor() || method->is_class_initializer() ||
method->is_overpass())) {
continue;
}
if (publicOnly && !method->is_public()) {
continue;
// Otherwise should probably put a method that throws NSME
result->obj_at_put(i, nullptr);
} else {
oop m;
if (want_constructor) {
+ assert(method->is_object_constructor(), "must be");
m = Reflection::new_constructor(method, CHECK_NULL);
} else {
m = Reflection::new_method(method, false, CHECK_NULL);
}
result->obj_at_put(i, m);
methodHandle m (THREAD, k->find_method(name, sig));
if (m.is_null()) {
THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class");
}
oop method;
! if (m->is_object_initializer()) {
method = Reflection::new_constructor(m, CHECK_NULL);
} else {
- // new_method accepts <clinit> as Method here
method = Reflection::new_method(m, true, CHECK_NULL);
}
return JNIHandles::make_local(THREAD, method);
}
methodHandle m (THREAD, k->find_method(name, sig));
if (m.is_null()) {
THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class");
}
oop method;
! if (m->is_object_constructor()) {
method = Reflection::new_constructor(m, CHECK_NULL);
} else {
method = Reflection::new_method(m, true, CHECK_NULL);
}
return JNIHandles::make_local(THREAD, method);
}
JvmtiVMObjectAllocEventCollector oam;
oop asd = JavaAssertions::createAssertionStatusDirectives(CHECK_NULL);
return JNIHandles::make_local(THREAD, asd);
JVM_END
+ // Arrays support /////////////////////////////////////////////////////////////
+
+ JVM_ENTRY(jboolean, JVM_ArrayIsAccessAtomic(JNIEnv *env, jclass unused, jobject array))
+ oop o = JNIHandles::resolve(array);
+ Klass* k = o->klass();
+ if ((o == nullptr) || (!k->is_array_klass())) {
+ THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+ }
+ return ArrayKlass::cast(k)->element_access_must_be_atomic();
+ JVM_END
+
+ JVM_ENTRY(jobject, JVM_ArrayEnsureAccessAtomic(JNIEnv *env, jclass unused, jobject array))
+ oop o = JNIHandles::resolve(array);
+ Klass* k = o->klass();
+ if ((o == nullptr) || (!k->is_array_klass())) {
+ THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+ }
+ if (k->is_flatArray_klass()) {
+ FlatArrayKlass* vk = FlatArrayKlass::cast(k);
+ if (!vk->element_access_must_be_atomic()) {
+ /**
+ * Need to decide how to implement:
+ *
+ * 1) Change to objArrayOop layout, therefore oop->klass() differs so
+ * then "<atomic>[Qfoo;" klass needs to subclass "[Qfoo;" to pass through
+ * "checkcast" & "instanceof"
+ *
+ * 2) Use extra header in the flatArrayOop to flag atomicity required and
+ * possibly per instance lock structure. Said info, could be placed in
+ * "trailer" rather than disturb the current arrayOop
+ */
+ Unimplemented();
+ }
+ }
+ return array;
+ JVM_END
+
// Verification ////////////////////////////////////////////////////////////////////////////////
// Reflection for the verifier /////////////////////////////////////////////////////////////////
// RedefineClasses support: bug 6214132 caused verification to fail.
JVM_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index))
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
! return InstanceKlass::cast(k)->field_access_flags(field_index) & JVM_RECOGNIZED_FIELD_MODIFIERS;
JVM_END
JVM_ENTRY(jint, JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index))
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
JVM_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index))
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
! return InstanceKlass::cast(k)->field_access_flags(field_index);
JVM_END
JVM_ENTRY(jint, JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index))
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
JVM_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index))
ResourceMark rm(THREAD);
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
Method* method = InstanceKlass::cast(k)->methods()->at(method_index);
! return method->name() == vmSymbols::object_initializer_name();
JVM_END
JVM_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index))
ResourceMark rm(THREAD);
JVM_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index))
ResourceMark rm(THREAD);
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
Method* method = InstanceKlass::cast(k)->methods()->at(method_index);
! return method->is_object_constructor();
JVM_END
JVM_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index))
ResourceMark rm(THREAD);
Symbol* name = cp->uncached_name_ref_at(cp_index);
Symbol* signature = cp->uncached_signature_ref_at(cp_index);
InstanceKlass* ik = InstanceKlass::cast(k_called);
for (JavaFieldStream fs(ik); !fs.done(); fs.next()) {
if (fs.name() == name && fs.signature() == signature) {
! return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS;
}
}
return -1;
}
default:
Symbol* name = cp->uncached_name_ref_at(cp_index);
Symbol* signature = cp->uncached_signature_ref_at(cp_index);
InstanceKlass* ik = InstanceKlass::cast(k_called);
for (JavaFieldStream fs(ik); !fs.done(); fs.next()) {
if (fs.name() == name && fs.signature() == signature) {
! return fs.access_flags().as_short();
}
}
return -1;
}
default:
JVM_LEAF(jboolean, JVM_IsPreviewEnabled(void))
return Arguments::enable_preview() ? JNI_TRUE : JNI_FALSE;
JVM_END
+ JVM_LEAF(jboolean, JVM_IsValhallaEnabled(void))
+ return EnableValhalla ? JNI_TRUE : JNI_FALSE;
+ JVM_END
+
JVM_LEAF(jboolean, JVM_IsContinuationsSupported(void))
return VMContinuations ? JNI_TRUE : JNI_FALSE;
JVM_END
JVM_LEAF(jboolean, JVM_IsForeignLinkerSupported(void))
JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
Handle method_handle;
if (thread->stack_overflow_state()->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) {
method_handle = Handle(THREAD, JNIHandles::resolve(method));
Handle receiver(THREAD, JNIHandles::resolve(obj));
! objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL);
jobject res = JNIHandles::make_local(THREAD, result);
if (JvmtiExport::should_post_vm_object_alloc()) {
oop ret_type = java_lang_reflect_Method::return_type(method_handle());
assert(ret_type != nullptr, "sanity check: ret_type oop must not be null!");
JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
Handle method_handle;
if (thread->stack_overflow_state()->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) {
method_handle = Handle(THREAD, JNIHandles::resolve(method));
Handle receiver(THREAD, JNIHandles::resolve(obj));
! objArrayHandle args = oopFactory::ensure_objArray(JNIHandles::resolve(args0), CHECK_NULL);
oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL);
jobject res = JNIHandles::make_local(THREAD, result);
if (JvmtiExport::should_post_vm_object_alloc()) {
oop ret_type = java_lang_reflect_Method::return_type(method_handle());
assert(ret_type != nullptr, "sanity check: ret_type oop must not be null!");
}
JVM_END
JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0))
oop constructor_mirror = JNIHandles::resolve(c);
- objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);
jobject res = JNIHandles::make_local(THREAD, result);
if (JvmtiExport::should_post_vm_object_alloc()) {
JvmtiExport::post_vm_object_alloc(thread, result);
}
}
JVM_END
JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0))
+ objArrayHandle args = oopFactory::ensure_objArray(JNIHandles::resolve(args0), CHECK_NULL);
oop constructor_mirror = JNIHandles::resolve(c);
oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);
jobject res = JNIHandles::make_local(THREAD, result);
if (JvmtiExport::should_post_vm_object_alloc()) {
JvmtiExport::post_vm_object_alloc(thread, result);
}
< prev index next >