Change remaining well known methods to `ArtMethod*`.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: I9cfef2a2c302f70826ac762202421388213e60e6
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index f2e0a6e..1754a68 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -110,7 +110,6 @@
#include "stream/file_output_stream.h"
#include "vdex_file.h"
#include "verifier/verifier_deps.h"
-#include "well_known_classes.h"
namespace art {
@@ -2754,7 +2753,6 @@
Thread* self = Thread::Current();
runtime_->GetClassLinker()->RunEarlyRootClinits(self);
InitializeIntrinsics();
- WellKnownClasses::Init(self->GetJniEnv());
runtime_->RunRootClinits(self);
// Runtime::Create acquired the mutator_lock_ that is normally given away when we
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index 0c0b569..b5bc35e 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -174,12 +174,7 @@
static void WaitForSystemDaemonStart(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
- {
- art::ScopedThreadStateChange strc(self, art::ThreadState::kNative);
- JNIEnv* jni = self->GetJniEnv();
- jni->CallStaticVoidMethod(art::WellKnownClasses::java_lang_Daemons,
- art::WellKnownClasses::java_lang_Daemons_waitForDaemonStart);
- }
+ art::WellKnownClasses::java_lang_Daemons_waitForDaemonStart->InvokeStatic<'V'>(self);
if (self->IsExceptionPending()) {
LOG(WARNING) << "Exception occurred when waiting for system daemons to start: "
<< self->GetException()->Dump();
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index a421461..a51e28f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1108,8 +1108,17 @@
Handle<mirror::ObjectArray<mirror::Class>> class_roots = hs.NewHandle(GetClassRoots());
EnsureRootInitialized(this, self, GetClassRoot<mirror::Class>(class_roots.Get()));
EnsureRootInitialized(this, self, GetClassRoot<mirror::String>(class_roots.Get()));
- // Field class is needed for register_java_net_InetAddress in libcore, b/28153851.
+ // `Field` class is needed for register_java_net_InetAddress in libcore, b/28153851.
EnsureRootInitialized(this, self, GetClassRoot<mirror::Field>(class_roots.Get()));
+
+ WellKnownClasses::Init(self->GetJniEnv());
+
+ // `FinalizerReference` class is needed for initialization of `java.net.InetAddress`.
+ // (Indirectly by constructing a `ObjectStreamField` which uses a `StringBuilder`
+ // and, when resizing, initializes the `System` class for `System.arraycopy()`
+ // and `System.<clinit> creates a finalizable object.)
+ EnsureRootInitialized(
+ this, self, WellKnownClasses::java_lang_ref_FinalizerReference_add->GetDeclaringClass());
}
void ClassLinker::RunRootClinits(Thread* self) {
@@ -1142,15 +1151,25 @@
WellKnownClasses::java_lang_Long_valueOf,
WellKnownClasses::java_lang_Short_valueOf,
// Ensure class loader classes are initialized (avoid check at runtime).
- // Superclasses `ClassLoader` and `BaseDexClassLoader` are initialized implicitly.
+ // Superclass `ClassLoader` is a class root and already initialized above.
+ // Superclass `BaseDexClassLoader` is initialized implicitly.
WellKnownClasses::dalvik_system_DelegateLastClassLoader_init,
WellKnownClasses::dalvik_system_DexClassLoader_init,
WellKnownClasses::dalvik_system_InMemoryDexClassLoader_init,
WellKnownClasses::dalvik_system_PathClassLoader_init,
WellKnownClasses::java_lang_BootClassLoader_init,
+ // Ensure `Daemons` class is initialized (avoid check at runtime).
+ WellKnownClasses::java_lang_Daemons_start,
// Ensure `Thread` and `ThreadGroup` classes are initialized (avoid check at runtime).
WellKnownClasses::java_lang_Thread_init,
WellKnownClasses::java_lang_ThreadGroup_add,
+ // Ensure reference classes are initialized (avoid check at runtime).
+ // The `FinalizerReference` class was initialized in `RunEarlyRootClinits()`.
+ WellKnownClasses::java_lang_ref_ReferenceQueue_add,
+ // Ensure `InvocationTargetException` class is initialized (avoid check at runtime).
+ WellKnownClasses::java_lang_reflect_InvocationTargetException_init,
+ // Ensure `Parameter` class is initialized (avoid check at runtime).
+ WellKnownClasses::java_lang_reflect_Parameter_init,
// Ensure `MethodHandles` class is initialized (avoid check at runtime).
WellKnownClasses::java_lang_invoke_MethodHandles_lookup,
// Ensure `DirectByteBuffer` class is initialized (avoid check at runtime).
@@ -1179,6 +1198,11 @@
for (ArtField* field : static_fields_of_classes_to_initialize) {
EnsureRootInitialized(this, self, field->GetDeclaringClass());
}
+
+ // This invariant is important since otherwise we will have the entire proxy invoke system
+ // confused.
+ DCHECK_NE(WellKnownClasses::java_lang_reflect_Proxy_init->GetEntryPointFromQuickCompiledCode(),
+ GetQuickInstrumentationEntryPoint());
}
ALWAYS_INLINE
@@ -5103,8 +5127,7 @@
// Find the <init>(InvocationHandler)V method. The exact method offset varies depending
// on which front-end compiler was used to build the libcore DEX files.
- ArtMethod* proxy_constructor =
- jni::DecodeArtMethod(WellKnownClasses::java_lang_reflect_Proxy_init);
+ ArtMethod* proxy_constructor = WellKnownClasses::java_lang_reflect_Proxy_init;
DCHECK(proxy_constructor != nullptr)
<< "Could not find <init> method in java.lang.reflect.Proxy";
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 6a22a66..0e8a962 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -160,7 +160,6 @@
ScopedObjectAccess soa(Thread::Current());
runtime_->GetClassLinker()->RunEarlyRootClinits(soa.Self());
InitializeIntrinsics();
- WellKnownClasses::Init(Thread::Current()->GetJniEnv());
runtime_->RunRootClinits(soa.Self());
}
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 63d2aa4..ae6e98a 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -22,6 +22,7 @@
#include "base/mutex.h"
#include "base/sdk_version.h"
#include "class_linker-inl.h"
+#include "class_root-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/method_reference.h"
#include "entrypoints/entrypoint_utils-inl.h"
@@ -33,14 +34,14 @@
#include "mirror/class-inl.h"
#include "mirror/method.h"
#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
+#include "mirror/object_array-alloc-inl.h"
#include "nth_caller_visitor.h"
#include "oat_file.h"
#include "oat_file-inl.h"
#include "oat_quick_method_header.h"
#include "reflection.h"
#include "scoped_thread_state_change-inl.h"
-#include "well_known_classes.h"
+#include "well_known_classes-inl.h"
namespace art {
@@ -65,60 +66,70 @@
jobject rcvr_jobj,
jobject interface_method_jobj,
std::vector<jvalue>& args) {
- DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
+ StackHandleScope<4u> hs(soa.Self());
+ DCHECK(rcvr_jobj != nullptr);
+ Handle<mirror::Object> h_receiver = hs.NewHandle(soa.Decode<mirror::Object>(rcvr_jobj));
+ DCHECK(h_receiver->InstanceOf(GetClassRoot(ClassRoot::kJavaLangReflectProxy)));
+ Handle<mirror::Method> h_interface_method =
+ hs.NewHandle(soa.Decode<mirror::Method>(interface_method_jobj));
// Build argument array possibly triggering GC.
soa.Self()->AssertThreadSuspensionIsAllowable();
- jobjectArray args_jobj = nullptr;
+ auto h_args = hs.NewHandle<mirror::ObjectArray<mirror::Object>>(nullptr);
const JValue zero;
- uint32_t target_sdk_version = Runtime::Current()->GetTargetSdkVersion();
+ Runtime* runtime = Runtime::Current();
+ uint32_t target_sdk_version = runtime->GetTargetSdkVersion();
// Do not create empty arrays unless needed to maintain Dalvik bug compatibility.
if (args.size() > 0 || IsSdkVersionSetAndAtMost(target_sdk_version, SdkVersion::kL)) {
- args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, nullptr);
- if (args_jobj == nullptr) {
+ h_args.Assign(mirror::ObjectArray<mirror::Object>::Alloc(
+ soa.Self(), GetClassRoot<mirror::ObjectArray<mirror::Object>>(), args.size()));
+ if (h_args == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
return zero;
}
for (size_t i = 0; i < args.size(); ++i) {
+ ObjPtr<mirror::Object> value;
if (shorty[i + 1] == 'L') {
- jobject val = args[i].l;
- soa.Env()->SetObjectArrayElement(args_jobj, i, val);
+ value = soa.Decode<mirror::Object>(args[i].l);
} else {
JValue jv;
jv.SetJ(args[i].j);
- ObjPtr<mirror::Object> val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
- if (val == nullptr) {
+ value = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
+ if (value == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
return zero;
}
- soa.Decode<mirror::ObjectArray<mirror::Object>>(args_jobj)->Set<false>(i, val);
}
+ // We do not support `Proxy.invoke()` in a transaction.
+ h_args->SetWithoutChecks</*kActiveTransaction=*/ false>(i, value);
}
}
// Call Proxy.invoke(Proxy proxy, Method method, Object[] args).
- jvalue invocation_args[3];
- invocation_args[0].l = rcvr_jobj;
- invocation_args[1].l = interface_method_jobj;
- invocation_args[2].l = args_jobj;
- jobject result =
- soa.Env()->CallStaticObjectMethodA(WellKnownClasses::java_lang_reflect_Proxy,
- WellKnownClasses::java_lang_reflect_Proxy_invoke,
- invocation_args);
+ Handle<mirror::Object> h_result = hs.NewHandle(
+ WellKnownClasses::java_lang_reflect_Proxy_invoke->InvokeStatic<'L', 'L', 'L', 'L'>(
+ soa.Self(), h_receiver.Get(), h_interface_method.Get(), h_args.Get()));
// Unbox result and handle error conditions.
if (LIKELY(!soa.Self()->IsExceptionPending())) {
- if (shorty[0] == 'V' || (shorty[0] == 'L' && result == nullptr)) {
+ if (shorty[0] == 'V' || (shorty[0] == 'L' && h_result == nullptr)) {
// Do nothing.
return zero;
} else {
- ArtMethod* interface_method =
- soa.Decode<mirror::Method>(interface_method_jobj)->GetArtMethod();
- // This can cause thread suspension.
- ObjPtr<mirror::Class> result_type = interface_method->ResolveReturnType();
- ObjPtr<mirror::Object> result_ref = soa.Decode<mirror::Object>(result);
+ ObjPtr<mirror::Class> result_type;
+ if (shorty[0] == 'L') {
+ // This can cause thread suspension.
+ result_type = h_interface_method->GetArtMethod()->ResolveReturnType();
+ if (result_type == nullptr) {
+ DCHECK(soa.Self()->IsExceptionPending());
+ return zero;
+ }
+ } else {
+ result_type = runtime->GetClassLinker()->LookupPrimitiveClass(shorty[0]);
+ DCHECK(result_type != nullptr);
+ }
JValue result_unboxed;
- if (!UnboxPrimitiveForResult(result_ref, result_type, &result_unboxed)) {
+ if (!UnboxPrimitiveForResult(h_result.Get(), result_type, &result_unboxed)) {
DCHECK(soa.Self()->IsExceptionPending());
return zero;
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 55af720..3bda43d 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3826,12 +3826,11 @@
void Heap::AddFinalizerReference(Thread* self, ObjPtr<mirror::Object>* object) {
ScopedObjectAccess soa(self);
- ScopedLocalRef<jobject> arg(self->GetJniEnv(), soa.AddLocalReference<jobject>(*object));
- jvalue args[1];
- args[0].l = arg.get();
- InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_FinalizerReference_add, args);
- // Restore object in case it gets moved.
- *object = soa.Decode<mirror::Object>(arg.get());
+ StackHandleScope<1u> hs(self);
+ // Use handle wrapper to update the `*object` if the object gets moved.
+ HandleWrapperObjPtr<mirror::Object> h_object = hs.NewHandleWrapper(object);
+ WellKnownClasses::java_lang_ref_FinalizerReference_add->InvokeStatic<'V', 'L'>(
+ self, h_object.Get());
}
void Heap::RequestConcurrentGCAndSaveObject(Thread* self,
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 772174f..f24c942 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -363,9 +363,8 @@
}
void Run(Thread* thread) override {
ScopedObjectAccess soa(thread);
- jvalue args[1];
- args[0].l = cleared_references_;
- InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args);
+ WellKnownClasses::java_lang_ref_ReferenceQueue_add->InvokeStatic<'V', 'L'>(
+ thread, soa.Decode<mirror::Object>(cleared_references_));
soa.Env()->DeleteGlobalRef(cleared_references_);
}
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index c7393eb..6c68cdb 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -196,8 +196,7 @@
// Annoyingly this can be called before we have actually initialized WellKnownClasses so therefore
// we also need to check this based on the declaring-class descriptor. The check is valid because
// Proxy only has a single constructor.
- ArtMethod* well_known_proxy_init = jni::DecodeArtMethod(
- WellKnownClasses::java_lang_reflect_Proxy_init);
+ ArtMethod* well_known_proxy_init = WellKnownClasses::java_lang_reflect_Proxy_init;
if (well_known_proxy_init == method) {
return true;
}
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index 8e6e84f..ad2efc5 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -393,8 +393,7 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
ArtMethod* method = soa.Self()->GetCurrentMethod(nullptr);
// If we are running Runtime.nativeLoad, use the overriding ClassLoader it set.
- if (method ==
- jni::DecodeArtMethod<kEnableIndexIds>(WellKnownClasses::java_lang_Runtime_nativeLoad)) {
+ if (method == WellKnownClasses::java_lang_Runtime_nativeLoad) {
return soa.Decode<mirror::ClassLoader>(soa.Self()->GetClassLoaderOverride());
}
// If we have a method, use its ClassLoader for context.
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index adf81dc..87c9f6c 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -19,7 +19,7 @@
#include "android-base/stringprintf.h"
#include "nativehelper/jni_macros.h"
-#include "art_method-inl.h"
+#include "art_method-alloc-inl.h"
#include "class_root-inl.h"
#include "dex/dex_file_annotations.h"
#include "handle.h"
@@ -157,7 +157,7 @@
static jobjectArray Executable_getParameters0(JNIEnv* env, jobject javaMethod) {
ScopedFastNativeObjectAccess soa(env);
Thread* self = soa.Self();
- StackHandleScope<8> hs(self);
+ StackHandleScope<6> hs(self);
Handle<mirror::Method> executable = hs.NewHandle(soa.Decode<mirror::Method>(javaMethod));
ArtMethod* art_method = executable.Get()->GetArtMethod();
@@ -198,56 +198,36 @@
Handle<mirror::Class> parameter_array_class =
hs.NewHandle(
WellKnownClasses::ToClass(WellKnownClasses::java_lang_reflect_Parameter__array));
- Handle<mirror::ObjectArray<mirror::Object>> parameter_array =
- hs.NewHandle(
- mirror::ObjectArray<mirror::Object>::Alloc(self,
- parameter_array_class.Get(),
- names_count));
+ Handle<mirror::ObjectArray<mirror::Object>> parameter_array = hs.NewHandle(
+ mirror::ObjectArray<mirror::Object>::Alloc(self, parameter_array_class.Get(), names_count));
if (UNLIKELY(parameter_array == nullptr)) {
self->AssertPendingException();
return nullptr;
}
- Handle<mirror::Class> parameter_class =
- hs.NewHandle(WellKnownClasses::ToClass(WellKnownClasses::java_lang_reflect_Parameter));
- ArtMethod* parameter_init =
- jni::DecodeArtMethod(WellKnownClasses::java_lang_reflect_Parameter_init);
+ ArtMethod* parameter_init = WellKnownClasses::java_lang_reflect_Parameter_init;
// Mutable handles used in the loop below to ensure cleanup without scaling the number of
// handles by the number of parameters.
MutableHandle<mirror::String> name = hs.NewHandle<mirror::String>(nullptr);
- MutableHandle<mirror::Object> parameter = hs.NewHandle<mirror::Object>(nullptr);
// Populate the Parameter[] to return.
for (int32_t parameter_index = 0; parameter_index < names_count; parameter_index++) {
name.Assign(names.Get()->Get(parameter_index));
int32_t modifiers = access_flags.Get()->Get(parameter_index);
- // Allocate / initialize the Parameter to add to parameter_array.
- parameter.Assign(parameter_class->AllocObject(self));
+ // Create the Parameter to add to parameter_array.
+ ObjPtr<mirror::Object> parameter = parameter_init->NewObject<'L', 'I', 'L', 'I'>(
+ self, name, modifiers, executable, parameter_index);
if (UNLIKELY(parameter == nullptr)) {
- self->AssertPendingOOMException();
+ DCHECK(self->IsExceptionPending());
return nullptr;
}
- uint32_t args[5] = { PointerToLowMemUInt32(parameter.Get()),
- PointerToLowMemUInt32(name.Get()),
- static_cast<uint32_t>(modifiers),
- PointerToLowMemUInt32(executable.Get()),
- static_cast<uint32_t>(parameter_index)
- };
- JValue result;
- static const char* method_signature = "VLILI"; // return + parameter types
- parameter_init->Invoke(self, args, sizeof(args), &result, method_signature);
- if (UNLIKELY(self->IsExceptionPending())) {
- return nullptr;
- }
-
- // Store the Parameter in the Parameter[].
- parameter_array.Get()->Set(parameter_index, parameter.Get());
- if (UNLIKELY(self->IsExceptionPending())) {
- return nullptr;
- }
+ // We're initializing a newly allocated array object, so we do not need to record that under
+ // a transaction. If the transaction is aborted, the whole object shall be unreachable.
+ parameter_array->SetWithoutChecks</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+ parameter_index, parameter);
}
return soa.AddLocalReference<jobjectArray>(parameter_array.Get());
}
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 7b66210..ac8ec56 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -33,17 +33,6 @@
ProxyTest() {
use_boot_image_ = true; // Make the Runtime creation cheaper.
}
-
- void SetUp() override {
- CommonRuntimeTest::SetUp();
- // The creation of a Proxy class uses WellKnownClasses. These are not normally initialized by
- // CommonRuntimeTest so we need to do that now.
- WellKnownClasses::Clear();
- WellKnownClasses::Init(art::Thread::Current()->GetJniEnv());
- // Since we aren't actually calling any of the native functions we can just immediately call
- // LateInit after calling Init.
- WellKnownClasses::LateInit(art::Thread::Current()->GetJniEnv());
- }
};
// Creates a proxy class and check ClassHelper works correctly.
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 7ddf64d..bfe9c8f 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -17,7 +17,7 @@
#include "reflection-inl.h"
#include "art_field-inl.h"
-#include "art_method-inl.h"
+#include "art_method-alloc-inl.h"
#include "base/enums.h"
#include "class_linker.h"
#include "common_throws.h"
@@ -502,17 +502,17 @@
<< soa.Self()->GetException()->GetClass()->PrettyDescriptor();
} else {
// If we get another exception when we are trying to wrap, then just use that instead.
- ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
+ StackHandleScope<2u> hs(soa.Self());
+ Handle<mirror::Throwable> cause = hs.NewHandle(soa.Self()->GetException());
soa.Self()->ClearException();
- jobject exception_instance =
- soa.Env()->NewObject(WellKnownClasses::java_lang_reflect_InvocationTargetException,
- WellKnownClasses::java_lang_reflect_InvocationTargetException_init,
- th.get());
+ Handle<mirror::Object> exception_instance =
+ WellKnownClasses::java_lang_reflect_InvocationTargetException_init->NewObject<'L'>(
+ hs, soa.Self(), cause);
if (exception_instance == nullptr) {
soa.Self()->AssertPendingException();
return false;
}
- soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
+ soa.Self()->SetException(exception_instance->AsThrowable());
}
return false;
}
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index e0c2ea9..f25d446 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -434,8 +434,8 @@
if (IsFinishedStarting()) {
ScopedTrace trace2("Waiting for Daemons");
self->ClearException();
- self->GetJniEnv()->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,
- WellKnownClasses::java_lang_Daemons_stop);
+ ScopedObjectAccess soa(self);
+ WellKnownClasses::java_lang_Daemons_stop->InvokeStatic<'V'>(self);
}
// Shutdown any trace running.
@@ -1030,24 +1030,14 @@
GetInstructionSetString(kRuntimeISA));
}
- StartDaemonThreads();
-
- // Make sure the environment is still clean (no lingering local refs from starting daemon
- // threads).
{
ScopedObjectAccess soa(self);
+ StartDaemonThreads();
self->GetJniEnv()->AssertLocalsEmpty();
- }
- // Send the initialized phase event. Send it after starting the Daemon threads so that agents
- // cannot delay the daemon threads from starting forever.
- {
- ScopedObjectAccess soa(self);
+ // Send the initialized phase event. Send it after starting the Daemon threads so that agents
+ // cannot delay the daemon threads from starting forever.
callbacks_->NextRuntimePhase(RuntimePhaseCallback::RuntimePhase::kInit);
- }
-
- {
- ScopedObjectAccess soa(self);
self->GetJniEnv()->AssertLocalsEmpty();
}
@@ -1259,15 +1249,11 @@
Thread* self = Thread::Current();
- // Must be in the kNative state for calling native methods.
- CHECK_EQ(self->GetState(), ThreadState::kNative);
+ DCHECK_EQ(self->GetState(), ThreadState::kRunnable);
- JNIEnv* env = self->GetJniEnv();
- env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,
- WellKnownClasses::java_lang_Daemons_start);
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- LOG(FATAL) << "Error starting java.lang.Daemons";
+ WellKnownClasses::java_lang_Daemons_start->InvokeStatic<'V'>(self);
+ if (UNLIKELY(self->IsExceptionPending())) {
+ LOG(FATAL) << "Error starting java.lang.Daemons: " << self->GetException()->Dump();
}
VLOG(startup) << "Runtime::StartDaemonThreads exiting";
@@ -2172,10 +2158,6 @@
// Set up the native methods provided by the runtime itself.
RegisterRuntimeNativeMethods(env);
- // Initialize classes used in JNI. The initialization requires runtime native
- // methods to be loaded first.
- WellKnownClasses::Init(env);
-
// Then set up libjavacore / libopenjdk / libicu_jni ,which are just
// a regular JNI libraries with a regular JNI_OnLoad. Most JNI libraries can
// just use System.loadLibrary, but libcore can't because it's the library
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 89f4b82..d6f0e81 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -1188,7 +1188,7 @@
void RegisterRuntimeNativeMethods(JNIEnv* env);
void InitMetrics();
- void StartDaemonThreads();
+ void StartDaemonThreads() REQUIRES_SHARED(Locks::mutator_lock_);
void StartSignalCatcher();
void MaybeSaveJitProfilingInfo();
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 6f99431..771df58 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -24,11 +24,11 @@
#include <android-base/stringprintf.h>
#include "art_method-inl.h"
+#include "base/casts.h"
#include "base/enums.h"
#include "class_linker.h"
#include "class_root-inl.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
-#include "entrypoints/runtime_asm_entrypoints.h"
#include "handle_scope-inl.h"
#include "hidden_api.h"
#include "jni/java_vm_ext.h"
@@ -51,16 +51,12 @@
jclass WellKnownClasses::dalvik_annotation_optimization_NeverInline;
jclass WellKnownClasses::dalvik_system_EmulatedStackFrame;
jclass WellKnownClasses::java_lang_annotation_Annotation__array;
-jclass WellKnownClasses::java_lang_Daemons;
jclass WellKnownClasses::java_lang_Error;
jclass WellKnownClasses::java_lang_IllegalAccessError;
jclass WellKnownClasses::java_lang_NoClassDefFoundError;
jclass WellKnownClasses::java_lang_Object;
jclass WellKnownClasses::java_lang_OutOfMemoryError;
-jclass WellKnownClasses::java_lang_reflect_InvocationTargetException;
-jclass WellKnownClasses::java_lang_reflect_Parameter;
jclass WellKnownClasses::java_lang_reflect_Parameter__array;
-jclass WellKnownClasses::java_lang_reflect_Proxy;
jclass WellKnownClasses::java_lang_RuntimeException;
jclass WellKnownClasses::java_lang_StackOverflowError;
jclass WellKnownClasses::java_lang_StringFactory;
@@ -80,9 +76,9 @@
ArtMethod* WellKnownClasses::java_lang_Character_valueOf;
ArtMethod* WellKnownClasses::java_lang_ClassLoader_loadClass;
ArtMethod* WellKnownClasses::java_lang_ClassNotFoundException_init;
-jmethodID WellKnownClasses::java_lang_Daemons_start;
-jmethodID WellKnownClasses::java_lang_Daemons_stop;
-jmethodID WellKnownClasses::java_lang_Daemons_waitForDaemonStart;
+ArtMethod* WellKnownClasses::java_lang_Daemons_start;
+ArtMethod* WellKnownClasses::java_lang_Daemons_stop;
+ArtMethod* WellKnownClasses::java_lang_Daemons_waitForDaemonStart;
ArtMethod* WellKnownClasses::java_lang_Double_doubleToRawLongBits;
ArtMethod* WellKnownClasses::java_lang_Double_valueOf;
ArtMethod* WellKnownClasses::java_lang_Float_floatToRawIntBits;
@@ -93,13 +89,13 @@
ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_lookup;
ArtMethod* WellKnownClasses::java_lang_invoke_MethodHandles_Lookup_findConstructor;
ArtMethod* WellKnownClasses::java_lang_Long_valueOf;
-jmethodID WellKnownClasses::java_lang_ref_FinalizerReference_add;
-jmethodID WellKnownClasses::java_lang_ref_ReferenceQueue_add;
-jmethodID WellKnownClasses::java_lang_reflect_InvocationTargetException_init;
-jmethodID WellKnownClasses::java_lang_reflect_Parameter_init;
-jmethodID WellKnownClasses::java_lang_reflect_Proxy_init;
-jmethodID WellKnownClasses::java_lang_reflect_Proxy_invoke;
-jmethodID WellKnownClasses::java_lang_Runtime_nativeLoad;
+ArtMethod* WellKnownClasses::java_lang_ref_FinalizerReference_add;
+ArtMethod* WellKnownClasses::java_lang_ref_ReferenceQueue_add;
+ArtMethod* WellKnownClasses::java_lang_reflect_InvocationTargetException_init;
+ArtMethod* WellKnownClasses::java_lang_reflect_Parameter_init;
+ArtMethod* WellKnownClasses::java_lang_reflect_Proxy_init;
+ArtMethod* WellKnownClasses::java_lang_reflect_Proxy_invoke;
+ArtMethod* WellKnownClasses::java_lang_Runtime_nativeLoad;
ArtMethod* WellKnownClasses::java_lang_Short_valueOf;
ArtMethod* WellKnownClasses::java_lang_String_charAt;
ArtMethod* WellKnownClasses::java_lang_Thread_dispatchUncaughtException;
@@ -194,38 +190,6 @@
return field;
}
-static jmethodID CacheMethod(JNIEnv* env, jclass c, bool is_static,
- const char* name, const char* signature) {
- jmethodID mid;
- {
- ScopedObjectAccess soa(env);
- if (Runtime::Current()->GetJniIdType() != JniIdType::kSwapablePointer) {
- mid = jni::EncodeArtMethod</*kEnableIndexIds*/ true>(
- FindMethodJNI(soa, c, name, signature, is_static));
- } else {
- mid = jni::EncodeArtMethod</*kEnableIndexIds*/ false>(
- FindMethodJNI(soa, c, name, signature, is_static));
- }
- }
- if (mid == nullptr) {
- ScopedObjectAccess soa(env);
- if (soa.Self()->IsExceptionPending()) {
- LOG(FATAL_WITHOUT_ABORT) << soa.Self()->GetException()->Dump();
- }
- std::ostringstream os;
- WellKnownClasses::ToClass(c)->DumpClass(os, mirror::Class::kDumpClassFullDetail);
- LOG(FATAL) << "Couldn't find method \"" << name << "\" with signature \"" << signature << "\": "
- << os.str();
- }
- return mid;
-}
-
-static jmethodID CacheMethod(JNIEnv* env, const char* klass, bool is_static,
- const char* name, const char* signature) {
- ScopedLocalRef<jclass> java_class(env, env->FindClass(klass));
- return CacheMethod(env, java_class.get(), is_static, name, signature);
-}
-
static ArtMethod* CacheMethod(ObjPtr<mirror::Class> klass,
bool is_static,
const char* name,
@@ -357,16 +321,12 @@
dalvik_system_EmulatedStackFrame = CacheClass(env, "dalvik/system/EmulatedStackFrame");
java_lang_annotation_Annotation__array = CacheClass(env, "[Ljava/lang/annotation/Annotation;");
- java_lang_Daemons = CacheClass(env, "java/lang/Daemons");
java_lang_Object = CacheClass(env, "java/lang/Object");
java_lang_OutOfMemoryError = CacheClass(env, "java/lang/OutOfMemoryError");
java_lang_Error = CacheClass(env, "java/lang/Error");
java_lang_IllegalAccessError = CacheClass(env, "java/lang/IllegalAccessError");
java_lang_NoClassDefFoundError = CacheClass(env, "java/lang/NoClassDefFoundError");
- java_lang_reflect_InvocationTargetException = CacheClass(env, "java/lang/reflect/InvocationTargetException");
- java_lang_reflect_Parameter = CacheClass(env, "java/lang/reflect/Parameter");
java_lang_reflect_Parameter__array = CacheClass(env, "[Ljava/lang/reflect/Parameter;");
- java_lang_reflect_Proxy = CacheClass(env, "java/lang/reflect/Proxy");
java_lang_RuntimeException = CacheClass(env, "java/lang/RuntimeException");
java_lang_StackOverflowError = CacheClass(env, "java/lang/StackOverflowError");
java_lang_StringFactory = CacheClass(env, "java/lang/StringFactory");
@@ -381,7 +341,7 @@
hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
hiddenapi::EnforcementPolicy::kDisabled);
- Thread* self = Thread::Current();
+ Thread* self = down_cast<JNIEnvExt*>(env)->GetSelf();
ScopedObjectAccess soa(self);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -402,17 +362,7 @@
java_lang_Short_valueOf =
CachePrimitiveBoxingMethod(class_linker, self, 'S', "Ljava/lang/Short;");
- java_lang_Daemons_start = CacheMethod(env, java_lang_Daemons, true, "start", "()V");
- java_lang_Daemons_stop = CacheMethod(env, java_lang_Daemons, true, "stop", "()V");
- java_lang_Daemons_waitForDaemonStart = CacheMethod(env, java_lang_Daemons, true, "waitForDaemonStart", "()V");
-
- java_lang_ref_FinalizerReference_add = CacheMethod(env, "java/lang/ref/FinalizerReference", true, "add", "(Ljava/lang/Object;)V");
- java_lang_ref_ReferenceQueue_add = CacheMethod(env, "java/lang/ref/ReferenceQueue", true, "add", "(Ljava/lang/ref/Reference;)V");
-
- java_lang_reflect_InvocationTargetException_init = CacheMethod(env, java_lang_reflect_InvocationTargetException, false, "<init>", "(Ljava/lang/Throwable;)V");
- java_lang_reflect_Parameter_init = CacheMethod(env, java_lang_reflect_Parameter, false, "<init>", "(Ljava/lang/String;ILjava/lang/reflect/Executable;I)V");
-
- StackHandleScope<28u> hs(self);
+ StackHandleScope<33u> hs(self);
Handle<mirror::Class> d_s_bdcl =
hs.NewHandle(FindSystemClass(class_linker, self, "Ldalvik/system/BaseDexClassLoader;"));
Handle<mirror::Class> d_s_dlcl =
@@ -439,6 +389,8 @@
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/ClassLoader;"));
Handle<mirror::Class> j_l_cnfe =
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/ClassNotFoundException;"));
+ Handle<mirror::Class> j_l_Daemons =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/Daemons;"));
Handle<mirror::Class> j_l_Thread =
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/Thread;"));
Handle<mirror::Class> j_l_tg =
@@ -449,6 +401,14 @@
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodHandles;"));
Handle<mirror::Class> j_l_i_MethodHandles_Lookup =
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/invoke/MethodHandles$Lookup;"));
+ Handle<mirror::Class> j_l_r_fr =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/ref/FinalizerReference;"));
+ Handle<mirror::Class> j_l_r_rq =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/ref/ReferenceQueue;"));
+ Handle<mirror::Class> j_l_rl_ite = hs.NewHandle(
+ FindSystemClass(class_linker, self, "Ljava/lang/reflect/InvocationTargetException;"));
+ Handle<mirror::Class> j_l_rl_Parameter =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/reflect/Parameter;"));
Handle<mirror::Class> j_n_b =
hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/nio/Buffer;"));
Handle<mirror::Class> j_n_bb =
@@ -534,6 +494,13 @@
java_lang_Float_floatToRawIntBits =
CacheMethod(j_l_Float, /*is_static=*/ true, "floatToRawIntBits", "(F)I", pointer_size);
+ java_lang_Daemons_start = CacheMethod(
+ j_l_Daemons.Get(), /*is_static=*/ true, "start", "()V", pointer_size);
+ java_lang_Daemons_stop = CacheMethod(
+ j_l_Daemons.Get(), /*is_static=*/ true, "stop", "()V", pointer_size);
+ java_lang_Daemons_waitForDaemonStart = CacheMethod(
+ j_l_Daemons.Get(), /*is_static=*/ true, "waitForDaemonStart", "()V", pointer_size);
+
ObjPtr<mirror::Class> j_l_String = GetClassRoot<mirror::String>(class_linker);
java_lang_String_charAt = CacheMethod(
j_l_String, /*is_static=*/ false, "charAt", "(I)C", pointer_size);
@@ -586,6 +553,34 @@
"(Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;",
pointer_size);
+ java_lang_ref_FinalizerReference_add = CacheMethod(
+ j_l_r_fr.Get(), /*is_static=*/ true, "add", "(Ljava/lang/Object;)V", pointer_size);
+ java_lang_ref_ReferenceQueue_add = CacheMethod(
+ j_l_r_rq.Get(), /*is_static=*/ true, "add", "(Ljava/lang/ref/Reference;)V", pointer_size);
+
+ java_lang_reflect_InvocationTargetException_init = CacheMethod(
+ j_l_rl_ite.Get(), /*is_static=*/ false, "<init>", "(Ljava/lang/Throwable;)V", pointer_size);
+ java_lang_reflect_Parameter_init = CacheMethod(
+ j_l_rl_Parameter.Get(),
+ /*is_static=*/ false,
+ "<init>",
+ "(Ljava/lang/String;ILjava/lang/reflect/Executable;I)V",
+ pointer_size);
+
+ ObjPtr<mirror::Class> j_l_rl_Proxy = GetClassRoot<mirror::Proxy>(class_linker);
+ java_lang_reflect_Proxy_init = CacheMethod(
+ j_l_rl_Proxy,
+ /*is_static=*/ false,
+ "<init>",
+ "(Ljava/lang/reflect/InvocationHandler;)V",
+ pointer_size);
+ java_lang_reflect_Proxy_invoke = CacheMethod(
+ j_l_rl_Proxy,
+ /*is_static=*/ true,
+ "invoke",
+ "(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;",
+ pointer_size);
+
java_nio_Buffer_isDirect =
CacheMethod(j_n_b.Get(), /*is_static=*/ false, "isDirect", "()Z", pointer_size);
java_nio_DirectByteBuffer_init =
@@ -716,26 +711,32 @@
}
void WellKnownClasses::LateInit(JNIEnv* env) {
- // CacheField and CacheMethod will initialize their classes. Classes below
- // have clinit sections that call JNI methods. Late init is required
- // to make sure these JNI methods are available.
- ScopedLocalRef<jclass> java_lang_Runtime(env, env->FindClass("java/lang/Runtime"));
- java_lang_Runtime_nativeLoad =
- CacheMethod(env, java_lang_Runtime.get(), true, "nativeLoad",
- "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Class;)"
- "Ljava/lang/String;");
- java_lang_reflect_Proxy_init =
- CacheMethod(env, java_lang_reflect_Proxy, false, "<init>",
- "(Ljava/lang/reflect/InvocationHandler;)V");
- // This invariant is important since otherwise we will have the entire proxy invoke system
- // confused.
- DCHECK_NE(
- jni::DecodeArtMethod(java_lang_reflect_Proxy_init)->GetEntryPointFromQuickCompiledCode(),
- GetQuickInstrumentationEntryPoint());
- java_lang_reflect_Proxy_invoke =
- CacheMethod(env, java_lang_reflect_Proxy, true, "invoke",
- "(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;"
- "[Ljava/lang/Object;)Ljava/lang/Object;");
+ // Initialize the `Runtime` class that was previously initialized
+ // by `CacheMethod()` calling `FindMethodJNI()`.
+ // TODO: Move this initialization to `ClassLinker`.
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Thread* self = down_cast<JNIEnvExt*>(env)->GetSelf();
+ ScopedObjectAccess soa(self);
+ StackHandleScope<1u> hs(self);
+ Handle<mirror::Class> j_l_Runtime =
+ hs.NewHandle(FindSystemClass(class_linker, self, "Ljava/lang/Runtime;"));
+ bool success = class_linker->EnsureInitialized(
+ self, j_l_Runtime, /*can_init_fields=*/ true, /*can_init_parents=*/ true);
+ CHECK(success) << "Failed to initialize " << j_l_Runtime->PrettyDescriptor();
+
+ // The function `GetClassLoader()` in `jni_internal.cc` is checking if the caller
+ // is `java_lang_Runtime_nativeLoad` and, if so, returns the class loader override.
+ // However, this function is used several times between `WellKnownClasses::Init()`
+ // and setting up the override by the `Runtime` and requires that we take the other
+ // path, rather than returning the uninitialized override. Therefore we cannot
+ // initialize this well-known method early and require the `LateInit()`.
+ // TODO: Clean up the initialization steps.
+ java_lang_Runtime_nativeLoad = CacheMethod(
+ j_l_Runtime.Get(),
+ /*is_static=*/ true,
+ "nativeLoad",
+ "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/String;",
+ class_linker->GetImagePointerSize());
}
void WellKnownClasses::HandleJniIdTypeChange(JNIEnv* env) {
@@ -750,16 +751,12 @@
dalvik_annotation_optimization_NeverInline = nullptr;
dalvik_system_EmulatedStackFrame = nullptr;
java_lang_annotation_Annotation__array = nullptr;
- java_lang_Daemons = nullptr;
java_lang_Error = nullptr;
java_lang_IllegalAccessError = nullptr;
java_lang_NoClassDefFoundError = nullptr;
java_lang_Object = nullptr;
java_lang_OutOfMemoryError = nullptr;
- java_lang_reflect_InvocationTargetException = nullptr;
- java_lang_reflect_Parameter = nullptr;
java_lang_reflect_Parameter__array = nullptr;
- java_lang_reflect_Proxy = nullptr;
java_lang_RuntimeException = nullptr;
java_lang_StackOverflowError = nullptr;
java_lang_StringFactory = nullptr;
@@ -782,6 +779,7 @@
java_lang_ClassNotFoundException_init = nullptr;
java_lang_Daemons_start = nullptr;
java_lang_Daemons_stop = nullptr;
+ java_lang_Daemons_waitForDaemonStart = nullptr;
java_lang_Double_doubleToRawLongBits = nullptr;
java_lang_Double_valueOf = nullptr;
java_lang_Float_floatToRawIntBits = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index f3da722..56e49db 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -96,16 +96,12 @@
static jclass dalvik_annotation_optimization_NeverInline;
static jclass dalvik_system_EmulatedStackFrame;
static jclass java_lang_annotation_Annotation__array;
- static jclass java_lang_Daemons;
static jclass java_lang_Error;
static jclass java_lang_IllegalAccessError;
static jclass java_lang_NoClassDefFoundError;
static jclass java_lang_Object;
static jclass java_lang_OutOfMemoryError;
- static jclass java_lang_reflect_InvocationTargetException;
- static jclass java_lang_reflect_Parameter;
static jclass java_lang_reflect_Parameter__array;
- static jclass java_lang_reflect_Proxy;
static jclass java_lang_RuntimeException;
static jclass java_lang_StackOverflowError;
static jclass java_lang_StringFactory;
@@ -125,9 +121,9 @@
static ArtMethod* java_lang_Character_valueOf;
static ArtMethod* java_lang_ClassLoader_loadClass;
static ArtMethod* java_lang_ClassNotFoundException_init;
- static jmethodID java_lang_Daemons_start;
- static jmethodID java_lang_Daemons_stop;
- static jmethodID java_lang_Daemons_waitForDaemonStart;
+ static ArtMethod* java_lang_Daemons_start;
+ static ArtMethod* java_lang_Daemons_stop;
+ static ArtMethod* java_lang_Daemons_waitForDaemonStart;
static ArtMethod* java_lang_Double_doubleToRawLongBits;
static ArtMethod* java_lang_Double_valueOf;
static ArtMethod* java_lang_Float_floatToRawIntBits;
@@ -138,13 +134,13 @@
static ArtMethod* java_lang_invoke_MethodHandles_lookup;
static ArtMethod* java_lang_invoke_MethodHandles_Lookup_findConstructor;
static ArtMethod* java_lang_Long_valueOf;
- static jmethodID java_lang_ref_FinalizerReference_add;
- static jmethodID java_lang_ref_ReferenceQueue_add;
- static jmethodID java_lang_reflect_InvocationTargetException_init;
- static jmethodID java_lang_reflect_Parameter_init;
- static jmethodID java_lang_reflect_Proxy_init;
- static jmethodID java_lang_reflect_Proxy_invoke;
- static jmethodID java_lang_Runtime_nativeLoad;
+ static ArtMethod* java_lang_ref_FinalizerReference_add;
+ static ArtMethod* java_lang_ref_ReferenceQueue_add;
+ static ArtMethod* java_lang_reflect_InvocationTargetException_init;
+ static ArtMethod* java_lang_reflect_Parameter_init;
+ static ArtMethod* java_lang_reflect_Proxy_init;
+ static ArtMethod* java_lang_reflect_Proxy_invoke;
+ static ArtMethod* java_lang_Runtime_nativeLoad;
static ArtMethod* java_lang_Short_valueOf;
static ArtMethod* java_lang_String_charAt;
static ArtMethod* java_lang_Thread_dispatchUncaughtException;
@@ -222,8 +218,13 @@
dalvik_system_PathClassLoader;
static constexpr ClassFromMethod<&java_lang_BootClassLoader_init> java_lang_BootClassLoader;
static constexpr ClassFromField<&java_lang_ClassLoader_parent> java_lang_ClassLoader;
+ static constexpr ClassFromMethod<&java_lang_Daemons_start> java_lang_Daemons;
static constexpr ClassFromField<&java_lang_Thread_daemon> java_lang_Thread;
static constexpr ClassFromField<&java_lang_ThreadGroup_groups> java_lang_ThreadGroup;
+ static constexpr ClassFromMethod<&java_lang_reflect_InvocationTargetException_init>
+ java_lang_reflect_InvocationTargetException;
+ static constexpr ClassFromMethod<&java_lang_reflect_Parameter_init>
+ java_lang_reflect_Parameter;
static constexpr ClassFromField<&java_nio_Buffer_address> java_nio_Buffer;
static constexpr ClassFromField<&java_util_Collections_EMPTY_LIST> java_util_Collections;
static constexpr ClassFromField<&libcore_util_EmptyArray_STACK_TRACE_ELEMENT>