1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_PROXY_TEST_H_ 18 #define ART_RUNTIME_PROXY_TEST_H_ 19 20 #include <jni.h> 21 #include <vector> 22 23 #include "art_method-inl.h" 24 #include "class_linker-inl.h" 25 #include "mirror/class-inl.h" 26 #include "mirror/method.h" 27 28 namespace art { 29 namespace proxy_test { 30 31 // Generate a proxy class with the given name and interfaces. This is a simplification from what 32 // libcore does to fit to our test needs. We do not check for duplicated interfaces or methods and 33 // we do not declare exceptions. 34 mirror::Class* GenerateProxyClass(ScopedObjectAccess& soa, 35 jobject jclass_loader, 36 ClassLinker* class_linker, 37 const char* className, 38 const std::vector<mirror::Class*>& interfaces) 39 REQUIRES_SHARED(Locks::mutator_lock_) { 40 mirror::Class* javaLangObject = class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); 41 CHECK(javaLangObject != nullptr); 42 43 jclass javaLangClass = soa.AddLocalReference<jclass>(mirror::Class::GetJavaLangClass()); 44 45 // Builds the interfaces array. 46 jobjectArray proxyClassInterfaces = soa.Env()->NewObjectArray(interfaces.size(), javaLangClass, 47 nullptr); 48 soa.Self()->AssertNoPendingException(); 49 for (size_t i = 0; i < interfaces.size(); ++i) { 50 soa.Env()->SetObjectArrayElement(proxyClassInterfaces, i, 51 soa.AddLocalReference<jclass>(interfaces[i])); 52 } 53 54 // Builds the method array. 55 jsize methods_count = 3; // Object.equals, Object.hashCode and Object.toString. 56 for (mirror::Class* interface : interfaces) { 57 methods_count += interface->NumVirtualMethods(); 58 } 59 jobjectArray proxyClassMethods = soa.Env()->NewObjectArray( 60 methods_count, soa.AddLocalReference<jclass>(mirror::Method::StaticClass()), nullptr); 61 soa.Self()->AssertNoPendingException(); 62 63 jsize array_index = 0; 64 // Fill the method array 65 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize); 66 ArtMethod* method = javaLangObject->FindClassMethod( 67 "equals", "(Ljava/lang/Object;)Z", kRuntimePointerSize); 68 CHECK(method != nullptr); 69 CHECK(!method->IsDirect()); 70 CHECK(method->GetDeclaringClass() == javaLangObject); 71 DCHECK(!Runtime::Current()->IsActiveTransaction()); 72 soa.Env()->SetObjectArrayElement( 73 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>( 74 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method))); 75 method = javaLangObject->FindClassMethod("hashCode", "()I", kRuntimePointerSize); 76 CHECK(method != nullptr); 77 CHECK(!method->IsDirect()); 78 CHECK(method->GetDeclaringClass() == javaLangObject); 79 soa.Env()->SetObjectArrayElement( 80 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>( 81 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method))); 82 method = javaLangObject->FindClassMethod( 83 "toString", "()Ljava/lang/String;", kRuntimePointerSize); 84 CHECK(method != nullptr); 85 CHECK(!method->IsDirect()); 86 CHECK(method->GetDeclaringClass() == javaLangObject); 87 soa.Env()->SetObjectArrayElement( 88 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>( 89 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method))); 90 // Now adds all interfaces virtual methods. 91 for (mirror::Class* interface : interfaces) { 92 for (auto& m : interface->GetDeclaredVirtualMethods(kRuntimePointerSize)) { 93 soa.Env()->SetObjectArrayElement( 94 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>( 95 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), &m))); 96 } 97 } 98 CHECK_EQ(array_index, methods_count); 99 100 // Builds an empty exception array. 101 jobjectArray proxyClassThrows = soa.Env()->NewObjectArray(0, javaLangClass, nullptr); 102 soa.Self()->AssertNoPendingException(); 103 104 mirror::Class* proxyClass = class_linker->CreateProxyClass( 105 soa, soa.Env()->NewStringUTF(className), proxyClassInterfaces, jclass_loader, 106 proxyClassMethods, proxyClassThrows); 107 soa.Self()->AssertNoPendingException(); 108 return proxyClass; 109 } 110 111 } // namespace proxy_test 112 } // namespace art 113 114 #endif // ART_RUNTIME_PROXY_TEST_H_ 115