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 | 13 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_class.cc | 73 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_class.h | 50 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_method.cc | 12 | ||||
| -rwxr-xr-x | test/912-classes/build | 17 | ||||
| -rw-r--r-- | test/912-classes/classes.cc | 82 | ||||
| -rw-r--r-- | test/912-classes/classes.h | 30 | ||||
| -rw-r--r-- | test/912-classes/expected.txt | 7 | ||||
| -rw-r--r-- | test/912-classes/info.txt | 1 | ||||
| -rwxr-xr-x | test/912-classes/run | 43 | ||||
| -rw-r--r-- | test/912-classes/src/Main.java | 61 | ||||
| -rw-r--r-- | test/Android.bp | 1 | ||||
| -rw-r--r-- | test/ti-agent/common_load.cc | 2 |
15 files changed, 383 insertions, 13 deletions
diff --git a/runtime/openjdkjvmti/Android.bp b/runtime/openjdkjvmti/Android.bp index 8b6a8f95df..5095cfd790 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_class.cc", "ti_method.cc", "ti_stack.cc", "transform.cc"], diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index 10e877a62f..9ff84fa8d8 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_class.h" #include "ti_method.h" #include "ti_stack.h" #include "transform.h" @@ -506,7 +507,7 @@ class JvmtiFunctions { jclass klass, char** signature_ptr, char** generic_ptr) { - return ERR(NOT_IMPLEMENTED); + return ClassUtil::GetClassSignature(env, klass, signature_ptr, generic_ptr); } static jvmtiError GetClassStatus(jvmtiEnv* env, jclass klass, jint* status_ptr) { diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h index 78cb9a04dc..a321124244 100644 --- a/runtime/openjdkjvmti/art_jvmti.h +++ b/runtime/openjdkjvmti/art_jvmti.h @@ -108,6 +108,19 @@ static inline JvmtiUniquePtr MakeJvmtiUniquePtr(jvmtiEnv* env, unsigned char* me return JvmtiUniquePtr(mem, JvmtiDeleter(env)); } +ALWAYS_INLINE +static inline 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; +} + } // namespace openjdkjvmti #endif // ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_ diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc new file mode 100644 index 0000000000..de2076aaef --- /dev/null +++ b/runtime/openjdkjvmti/ti_class.cc @@ -0,0 +1,73 @@ +/* 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_class.h" + +#include "art_jvmti.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-inl.h" + +namespace openjdkjvmti { + +jvmtiError ClassUtil::GetClassSignature(jvmtiEnv* env, + jclass jklass, + char** signature_ptr, + char** generic_ptr) { + art::ScopedObjectAccess soa(art::Thread::Current()); + art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass); + if (klass == nullptr) { + return ERR(INVALID_CLASS); + } + + JvmtiUniquePtr sig_copy; + if (signature_ptr != nullptr) { + std::string storage; + const char* descriptor = klass->GetDescriptor(&storage); + + unsigned char* tmp; + jvmtiError ret = CopyString(env, descriptor, &tmp); + if (ret != ERR(NONE)) { + return ret; + } + sig_copy = MakeJvmtiUniquePtr(env, tmp); + *signature_ptr = reinterpret_cast<char*>(tmp); + } + + // TODO: Support generic signature. + *generic_ptr = nullptr; + + // Everything is fine, release the buffers. + sig_copy.release(); + + return ERR(NONE); +} + +} // namespace openjdkjvmti diff --git a/runtime/openjdkjvmti/ti_class.h b/runtime/openjdkjvmti/ti_class.h new file mode 100644 index 0000000000..caa77d4f7d --- /dev/null +++ b/runtime/openjdkjvmti/ti_class.h @@ -0,0 +1,50 @@ +/* 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_CLASS_H_ +#define ART_RUNTIME_OPENJDKJVMTI_TI_CLASS_H_ + +#include "jni.h" +#include "jvmti.h" + +namespace openjdkjvmti { + +class ClassUtil { + public: + static jvmtiError GetClassSignature(jvmtiEnv* env, + jclass klass, + char** signature_ptr, + char** generic_ptr); +}; + +} // namespace openjdkjvmti + +#endif // ART_RUNTIME_OPENJDKJVMTI_TI_CLASS_H_ diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc index 8d943d93e7..f893e58f39 100644 --- a/runtime/openjdkjvmti/ti_method.cc +++ b/runtime/openjdkjvmti/ti_method.cc @@ -38,18 +38,6 @@ 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, diff --git a/test/912-classes/build b/test/912-classes/build new file mode 100755 index 0000000000..898e2e54a2 --- /dev/null +++ b/test/912-classes/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/912-classes/classes.cc b/test/912-classes/classes.cc new file mode 100644 index 0000000000..4bf329c8e1 --- /dev/null +++ b/test/912-classes/classes.cc @@ -0,0 +1,82 @@ +/* + * 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 "classes.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 Test912Classes { + +extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassSignature( + JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) { + char* sig; + char* gen; + jvmtiError result = jvmti_env->GetClassSignature(klass, &sig, &gen); + if (result != JVMTI_ERROR_NONE) { + char* err; + jvmti_env->GetErrorName(result, &err); + printf("Failure running GetClassSignature: %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(2, obj_class.get(), nullptr); + if (ret == nullptr) { + return ret; + } + + 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, sig_str.get()); + env->SetObjectArrayElement(ret, 1, gen_str.get()); + + // Need to deallocate the strings. + 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 Test912Classes +} // namespace art diff --git a/test/912-classes/classes.h b/test/912-classes/classes.h new file mode 100644 index 0000000000..62fb203356 --- /dev/null +++ b/test/912-classes/classes.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_912_CLASSES_CLASSES_H_ +#define ART_TEST_912_CLASSES_CLASSES_H_ + +#include <jni.h> + +namespace art { +namespace Test912Classes { + +jint OnLoad(JavaVM* vm, char* options, void* reserved); + +} // namespace Test912Classes +} // namespace art + +#endif // ART_TEST_912_CLASSES_CLASSES_H_ diff --git a/test/912-classes/expected.txt b/test/912-classes/expected.txt new file mode 100644 index 0000000000..71b22f4d0b --- /dev/null +++ b/test/912-classes/expected.txt @@ -0,0 +1,7 @@ +[Ljava/lang/Object;, null] +[Ljava/lang/String;, null] +[Ljava/lang/Math;, null] +[Ljava/util/List;, null] +[L$Proxy0;, null] +[I, null] +[[D, null] diff --git a/test/912-classes/info.txt b/test/912-classes/info.txt new file mode 100644 index 0000000000..875a5f6ec1 --- /dev/null +++ b/test/912-classes/info.txt @@ -0,0 +1 @@ +Tests basic functions in the jvmti plugin. diff --git a/test/912-classes/run b/test/912-classes/run new file mode 100755 index 0000000000..64bbb987a1 --- /dev/null +++ b/test/912-classes/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}=912-classes,${arg} \ + --android-runtime-option -Xplugin:${plugin} \ + ${other_args} \ + --args ${lib} diff --git a/test/912-classes/src/Main.java b/test/912-classes/src/Main.java new file mode 100644 index 0000000000..025584ec0a --- /dev/null +++ b/test/912-classes/src/Main.java @@ -0,0 +1,61 @@ +/* + * 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.Proxy; +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 { + testClass("java.lang.Object"); + testClass("java.lang.String"); + testClass("java.lang.Math"); + testClass("java.util.List"); + + testClass(getProxyClass()); + + testClass(int.class); + testClass(double[].class); + } + + private static Class<?> proxyClass = null; + + private static Class<?> getProxyClass() throws Exception { + if (proxyClass != null) { + return proxyClass; + } + + proxyClass = Proxy.getProxyClass(Main.class.getClassLoader(), new Class[] { Runnable.class }); + return proxyClass; + } + + private static void testClass(String className) throws Exception { + Class<?> base = Class.forName(className); + testClass(base); + } + + private static void testClass(Class<?> base) throws Exception { + String[] result = getClassSignature(base); + System.out.println(Arrays.toString(result)); + } + + private static native String[] getClassSignature(Class<?> c); +} diff --git a/test/Android.bp b/test/Android.bp index 37e1fc0dd7..af70486abf 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -255,6 +255,7 @@ art_cc_defaults { "909-attach-agent/attach.cc", "910-methods/methods.cc", "911-get-stack-trace/stack_trace.cc", + "912-classes/classes.cc", ], shared_libs: [ "libbase", diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc index 7faf700b6e..4db953cc4a 100644 --- a/test/ti-agent/common_load.cc +++ b/test/ti-agent/common_load.cc @@ -35,6 +35,7 @@ #include "909-attach-agent/attach.h" #include "910-methods/methods.h" #include "911-get-stack-trace/stack_trace.h" +#include "912-classes/classes.h" namespace art { @@ -62,6 +63,7 @@ AgentLib agents[] = { { "909-attach-agent", nullptr, Test909AttachAgent::OnAttach }, { "910-methods", Test910Methods::OnLoad, nullptr }, { "911-get-stack-trace", Test911GetStackTrace::OnLoad, nullptr }, + { "912-classes", Test912Classes::OnLoad, nullptr }, }; static AgentLib* FindAgent(char* name) { |