diff options
| -rw-r--r-- | runtime/openjdkjvmti/Android.bp | 1 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/OpenjdkJvmTi.cc | 3 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/art_jvmti.h | 28 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_method.cc | 100 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_method.h | 51 | ||||
| -rwxr-xr-x | test/910-methods/build | 17 | ||||
| -rw-r--r-- | test/910-methods/expected.txt | 4 | ||||
| -rw-r--r-- | test/910-methods/info.txt | 1 | ||||
| -rw-r--r-- | test/910-methods/methods.cc | 90 | ||||
| -rw-r--r-- | test/910-methods/methods.h | 30 | ||||
| -rwxr-xr-x | test/910-methods/run | 43 | ||||
| -rw-r--r-- | test/910-methods/src/Main.java | 43 | ||||
| -rw-r--r-- | test/Android.bp | 1 | ||||
| -rw-r--r-- | test/Android.run-test.mk | 1 | ||||
| -rw-r--r-- | test/ti-agent/common_load.cc | 2 |
15 files changed, 414 insertions, 1 deletions
diff --git a/runtime/openjdkjvmti/Android.bp b/runtime/openjdkjvmti/Android.bp index de6683cc83..c8675a4339 100644 --- a/runtime/openjdkjvmti/Android.bp +++ b/runtime/openjdkjvmti/Android.bp @@ -21,6 +21,7 @@ cc_defaults { "heap.cc", "object_tagging.cc", "OpenjdkJvmTi.cc", + "ti_method.cc", "transform.cc"], include_dirs: ["art/runtime"], shared_libs: [ diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index b91acb691c..ed99009b0f 100644 --- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc +++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc @@ -47,6 +47,7 @@ #include "scoped_thread_state_change-inl.h" #include "thread_list.h" #include "thread-inl.h" +#include "ti_method.h" #include "transform.h" // TODO Remove this at some point by annotating all the methods. It was put in to make the skeleton @@ -635,7 +636,7 @@ class JvmtiFunctions { char** name_ptr, char** signature_ptr, char** generic_ptr) { - return ERR(NOT_IMPLEMENTED); + return MethodUtil::GetMethodName(env, method, name_ptr, signature_ptr, generic_ptr); } static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env, diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h index 66d093782a..78cb9a04dc 100644 --- a/runtime/openjdkjvmti/art_jvmti.h +++ b/runtime/openjdkjvmti/art_jvmti.h @@ -37,6 +37,8 @@ #include <jni.h> #include "base/casts.h" +#include "base/logging.h" +#include "base/macros.h" #include "events.h" #include "java_vm_ext.h" #include "jni_env_ext.h" @@ -80,6 +82,32 @@ static inline JNIEnv* GetJniEnv(jvmtiEnv* env) { return ret_value; } +class JvmtiDeleter { + public: + JvmtiDeleter() : env_(nullptr) {} + explicit JvmtiDeleter(jvmtiEnv* env) : env_(env) {} + + JvmtiDeleter(JvmtiDeleter&) = default; + JvmtiDeleter(JvmtiDeleter&&) = default; + JvmtiDeleter& operator=(const JvmtiDeleter&) = default; + + void operator()(unsigned char* ptr) const { + CHECK(env_ != nullptr); + jvmtiError ret = env_->Deallocate(ptr); + CHECK(ret == ERR(NONE)); + } + + private: + mutable jvmtiEnv* env_; +}; + +using JvmtiUniquePtr = std::unique_ptr<unsigned char, JvmtiDeleter>; + +ALWAYS_INLINE +static inline JvmtiUniquePtr MakeJvmtiUniquePtr(jvmtiEnv* env, unsigned char* mem) { + return JvmtiUniquePtr(mem, JvmtiDeleter(env)); +} + } // namespace openjdkjvmti #endif // ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_ diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc new file mode 100644 index 0000000000..8d943d93e7 --- /dev/null +++ b/runtime/openjdkjvmti/ti_method.cc @@ -0,0 +1,100 @@ +/* Copyright (C) 2016 The Android Open Source Project + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This file implements interfaces from the file jvmti.h. This implementation + * is licensed under the same terms as the file jvmti.h. The + * copyright and license information for the file jvmti.h follows. + * + * Copyright (c) 2003, 2011, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +#include "ti_method.h" + +#include "art_jvmti.h" +#include "art_method-inl.h" +#include "base/enums.h" +#include "scoped_thread_state_change-inl.h" + +namespace openjdkjvmti { + +static jvmtiError CopyString(jvmtiEnv* env, const char* src, unsigned char** copy) { + size_t len = strlen(src) + 1; + unsigned char* buf; + jvmtiError ret = env->Allocate(len, &buf); + if (ret != ERR(NONE)) { + return ret; + } + strcpy(reinterpret_cast<char*>(buf), src); + *copy = buf; + return ret; +} + +jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env, + jmethodID method, + char** name_ptr, + char** signature_ptr, + char** generic_ptr) { + art::ScopedObjectAccess soa(art::Thread::Current()); + art::ArtMethod* art_method = soa.DecodeMethod(method); + art_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize); + + JvmtiUniquePtr name_copy; + if (name_ptr != nullptr) { + const char* method_name = art_method->GetName(); + if (method_name == nullptr) { + method_name = "<error>"; + } + unsigned char* tmp; + jvmtiError ret = CopyString(env, method_name, &tmp); + if (ret != ERR(NONE)) { + return ret; + } + name_copy = MakeJvmtiUniquePtr(env, tmp); + *name_ptr = reinterpret_cast<char*>(tmp); + } + + JvmtiUniquePtr signature_copy; + if (signature_ptr != nullptr) { + const art::Signature sig = art_method->GetSignature(); + std::string str = sig.ToString(); + unsigned char* tmp; + jvmtiError ret = CopyString(env, str.c_str(), &tmp); + if (ret != ERR(NONE)) { + return ret; + } + signature_copy = MakeJvmtiUniquePtr(env, tmp); + *signature_ptr = reinterpret_cast<char*>(tmp); + } + + // TODO: Support generic signature. + *generic_ptr = nullptr; + + // Everything is fine, release the buffers. + name_copy.release(); + signature_copy.release(); + + return ERR(NONE); +} + +} // namespace openjdkjvmti diff --git a/runtime/openjdkjvmti/ti_method.h b/runtime/openjdkjvmti/ti_method.h new file mode 100644 index 0000000000..17a37285fb --- /dev/null +++ b/runtime/openjdkjvmti/ti_method.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2016 The Android Open Source Project + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This file implements interfaces from the file jvmti.h. This implementation + * is licensed under the same terms as the file jvmti.h. The + * copyright and license information for the file jvmti.h follows. + * + * Copyright (c) 2003, 2011, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +#ifndef ART_RUNTIME_OPENJDKJVMTI_TI_METHOD_H_ +#define ART_RUNTIME_OPENJDKJVMTI_TI_METHOD_H_ + +#include "jni.h" +#include "jvmti.h" + +namespace openjdkjvmti { + +class MethodUtil { + public: + static jvmtiError GetMethodName(jvmtiEnv* env, + jmethodID method, + char** name_ptr, + char** signature_ptr, + char** generic_ptr); +}; + +} // namespace openjdkjvmti + +#endif // ART_RUNTIME_OPENJDKJVMTI_TI_METHOD_H_ diff --git a/test/910-methods/build b/test/910-methods/build new file mode 100755 index 0000000000..898e2e54a2 --- /dev/null +++ b/test/910-methods/build @@ -0,0 +1,17 @@ +#!/bin/bash +# +# Copyright 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +./default-build "$@" --experimental agents diff --git a/test/910-methods/expected.txt b/test/910-methods/expected.txt new file mode 100644 index 0000000000..b305d0f8ba --- /dev/null +++ b/test/910-methods/expected.txt @@ -0,0 +1,4 @@ +[toString, ()Ljava/lang/String;, null] +[charAt, (I)C, null] +[sqrt, (D)D, null] +[add, (Ljava/lang/Object;)Z, null] diff --git a/test/910-methods/info.txt b/test/910-methods/info.txt new file mode 100644 index 0000000000..875a5f6ec1 --- /dev/null +++ b/test/910-methods/info.txt @@ -0,0 +1 @@ +Tests basic functions in the jvmti plugin. diff --git a/test/910-methods/methods.cc b/test/910-methods/methods.cc new file mode 100644 index 0000000000..fa910c1aeb --- /dev/null +++ b/test/910-methods/methods.cc @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "methods.h" + +#include <stdio.h> + +#include "base/macros.h" +#include "jni.h" +#include "openjdkjvmti/jvmti.h" +#include "ScopedLocalRef.h" + +#include "ti-agent/common_load.h" + +namespace art { +namespace Test910Methods { + +extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getMethodName( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) { + jmethodID id = env->FromReflectedMethod(method); + + char* name; + char* sig; + char* gen; + jvmtiError result = jvmti_env->GetMethodName(id, &name, &sig, &gen); + if (result != JVMTI_ERROR_NONE) { + char* err; + jvmti_env->GetErrorName(result, &err); + printf("Failure running GetMethodName: %s\n", err); + return nullptr; + } + + ScopedLocalRef<jclass> obj_class(env, env->FindClass("java/lang/String")); + if (obj_class.get() == nullptr) { + return nullptr; + } + + jobjectArray ret = env->NewObjectArray(3, obj_class.get(), nullptr); + if (ret == nullptr) { + return ret; + } + + ScopedLocalRef<jstring> name_str(env, name == nullptr ? nullptr : env->NewStringUTF(name)); + ScopedLocalRef<jstring> sig_str(env, sig == nullptr ? nullptr : env->NewStringUTF(sig)); + ScopedLocalRef<jstring> gen_str(env, gen == nullptr ? nullptr : env->NewStringUTF(gen)); + + env->SetObjectArrayElement(ret, 0, name_str.get()); + env->SetObjectArrayElement(ret, 1, sig_str.get()); + env->SetObjectArrayElement(ret, 2, gen_str.get()); + + // Need to deallocate the strings. + if (name != nullptr) { + jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name)); + } + if (sig != nullptr) { + jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(sig)); + } + if (gen != nullptr) { + jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(gen)); + } + + return ret; +} + +// Don't do anything +jint OnLoad(JavaVM* vm, + char* options ATTRIBUTE_UNUSED, + void* reserved ATTRIBUTE_UNUSED) { + if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) { + printf("Unable to get jvmti env!\n"); + return 1; + } + return 0; +} + +} // namespace Test910Methods +} // namespace art diff --git a/test/910-methods/methods.h b/test/910-methods/methods.h new file mode 100644 index 0000000000..93d18741ed --- /dev/null +++ b/test/910-methods/methods.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_TEST_910_METHODS_METHODS_H_ +#define ART_TEST_910_METHODS_METHODS_H_ + +#include <jni.h> + +namespace art { +namespace Test910Methods { + +jint OnLoad(JavaVM* vm, char* options, void* reserved); + +} // namespace Test910Methods +} // namespace art + +#endif // ART_TEST_910_METHODS_METHODS_H_ diff --git a/test/910-methods/run b/test/910-methods/run new file mode 100755 index 0000000000..4dd2555f9e --- /dev/null +++ b/test/910-methods/run @@ -0,0 +1,43 @@ +#!/bin/bash +# +# Copyright 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +plugin=libopenjdkjvmtid.so +agent=libtiagentd.so +lib=tiagentd +if [[ "$@" == *"-O"* ]]; then + agent=libtiagent.so + plugin=libopenjdkjvmti.so + lib=tiagent +fi + +if [[ "$@" == *"--jvm"* ]]; then + arg="jvm" +else + arg="art" +fi + +if [[ "$@" != *"--debuggable"* ]]; then + other_args=" -Xcompiler-option --debuggable " +else + other_args="" +fi + +./default-run "$@" --experimental agents \ + --experimental runtime-plugins \ + --runtime-option -agentpath:${agent}=910-methods,${arg} \ + --android-runtime-option -Xplugin:${plugin} \ + ${other_args} \ + --args ${lib} diff --git a/test/910-methods/src/Main.java b/test/910-methods/src/Main.java new file mode 100644 index 0000000000..1af30ba878 --- /dev/null +++ b/test/910-methods/src/Main.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.lang.reflect.Method; +import java.util.Arrays; + +public class Main { + public static void main(String[] args) throws Exception { + System.loadLibrary(args[1]); + + doTest(); + } + + public static void doTest() throws Exception { + testMethod("java.lang.Object", "toString"); + testMethod("java.lang.String", "charAt", int.class); + testMethod("java.lang.Math", "sqrt", double.class); + testMethod("java.util.List", "add", Object.class); + } + + private static void testMethod(String className, String methodName, Class<?>... types) + throws Exception { + Class<?> base = Class.forName(className); + Method m = base.getDeclaredMethod(methodName, types); + String[] result = getMethodName(m); + System.out.println(Arrays.toString(result)); + } + + private static native String[] getMethodName(Method m); +} diff --git a/test/Android.bp b/test/Android.bp index be1864cc4e..9675ef52b4 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -253,6 +253,7 @@ art_cc_defaults { "907-get-loaded-classes/get_loaded_classes.cc", "908-gc-start-finish/gc_callbacks.cc", "909-attach-agent/attach.cc", + "910-methods/methods.cc", ], shared_libs: [ "libbase", diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index b140645004..fcb6f4d3fd 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -276,6 +276,7 @@ TEST_ART_BROKEN_TARGET_TESTS += \ 907-get-loaded-classes \ 908-gc-start-finish \ 909-attach-agent \ + 910-methods \ ifneq (,$(filter target,$(TARGET_TYPES))) ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES), \ diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc index 90d0a66fd7..5e8ef94334 100644 --- a/test/ti-agent/common_load.cc +++ b/test/ti-agent/common_load.cc @@ -33,6 +33,7 @@ #include "907-get-loaded-classes/get_loaded_classes.h" #include "908-gc-start-finish/gc_callbacks.h" #include "909-attach-agent/attach.h" +#include "910-methods/methods.h" namespace art { @@ -58,6 +59,7 @@ AgentLib agents[] = { { "907-get-loaded-classes", Test907GetLoadedClasses::OnLoad, nullptr }, { "908-gc-start-finish", Test908GcStartFinish::OnLoad, nullptr }, { "909-attach-agent", nullptr, Test909AttachAgent::OnAttach }, + { "910-methods", Test910Methods::OnLoad, nullptr }, }; static AgentLib* FindAgent(char* name) { |