• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/macros.h"
25 #include "class_linker-inl.h"
26 #include "class_root-inl.h"
27 #include "mirror/class-inl.h"
28 #include "mirror/method.h"
29 #include "obj_ptr-inl.h"
30 
31 namespace art HIDDEN {
32 namespace proxy_test {
33 
34 // Generate a proxy class with the given name and interfaces. This is a simplification from what
35 // libcore does to fit to our test needs. We do not check for duplicated interfaces or methods and
36 // we do not declare exceptions.
GenerateProxyClass(ScopedObjectAccess & soa,jobject jclass_loader,ClassLinker * class_linker,const char * className,const std::vector<Handle<mirror::Class>> & interfaces)37 inline ObjPtr<mirror::Class> GenerateProxyClass(ScopedObjectAccess& soa,
38                                                 jobject jclass_loader,
39                                                 ClassLinker* class_linker,
40                                                 const char* className,
41                                                 const std::vector<Handle<mirror::Class>>& interfaces)
42     REQUIRES_SHARED(Locks::mutator_lock_) {
43   StackHandleScope<1> hs(soa.Self());
44   Handle<mirror::Class> javaLangObject = hs.NewHandle(GetClassRoot<mirror::Object>());
45   CHECK(javaLangObject != nullptr);
46 
47   jclass javaLangClass = soa.AddLocalReference<jclass>(GetClassRoot<mirror::Class>());
48 
49   // Builds the interfaces array.
50   jobjectArray proxyClassInterfaces =
51       soa.Env()->NewObjectArray(interfaces.size(), javaLangClass, /* initialElement= */ nullptr);
52   soa.Self()->AssertNoPendingException();
53   for (size_t i = 0; i < interfaces.size(); ++i) {
54     soa.Env()->SetObjectArrayElement(proxyClassInterfaces, i,
55                                      soa.AddLocalReference<jclass>(interfaces[i].Get()));
56   }
57 
58   // Builds the method array.
59   jsize methods_count = 3;  // Object.equals, Object.hashCode and Object.toString.
60   for (Handle<mirror::Class> interface : interfaces) {
61     methods_count += interface->NumVirtualMethods();
62   }
63   jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(
64       methods_count,
65       soa.AddLocalReference<jclass>(GetClassRoot<mirror::Method>()),
66       /* initialElement= */ nullptr);
67   soa.Self()->AssertNoPendingException();
68 
69   jsize array_index = 0;
70   // Fill the method array
71   DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
72   ArtMethod* method = javaLangObject->FindClassMethod(
73       "equals", "(Ljava/lang/Object;)Z", kRuntimePointerSize);
74   CHECK(method != nullptr);
75   CHECK(!method->IsDirect());
76   CHECK(method->GetDeclaringClass() == javaLangObject.Get());
77   DCHECK(!Runtime::Current()->IsActiveTransaction());
78   soa.Env()->SetObjectArrayElement(
79       proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
80           mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method)));
81   method = javaLangObject->FindClassMethod("hashCode", "()I", kRuntimePointerSize);
82   CHECK(method != nullptr);
83   CHECK(!method->IsDirect());
84   CHECK(method->GetDeclaringClass() == javaLangObject.Get());
85   soa.Env()->SetObjectArrayElement(
86       proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
87           mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method)));
88   method = javaLangObject->FindClassMethod(
89       "toString", "()Ljava/lang/String;", kRuntimePointerSize);
90   CHECK(method != nullptr);
91   CHECK(!method->IsDirect());
92   CHECK(method->GetDeclaringClass() == javaLangObject.Get());
93   soa.Env()->SetObjectArrayElement(
94       proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
95           mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method)));
96   // Now adds all interfaces virtual methods.
97   for (Handle<mirror::Class> interface : interfaces) {
98     for (auto& m : interface->GetDeclaredVirtualMethods(kRuntimePointerSize)) {
99       soa.Env()->SetObjectArrayElement(
100           proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
101               mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), &m)));
102     }
103   }
104   CHECK_EQ(array_index, methods_count);
105 
106   // Builds an empty exception array.
107   jobjectArray proxyClassThrows = soa.Env()->NewObjectArray(0, javaLangClass, nullptr);
108   soa.Self()->AssertNoPendingException();
109 
110   ObjPtr<mirror::Class> proxyClass = class_linker->CreateProxyClass(
111       soa,
112       soa.Env()->NewStringUTF(className),
113       proxyClassInterfaces,
114       jclass_loader,
115       proxyClassMethods,
116       proxyClassThrows);
117   soa.Self()->AssertNoPendingException();
118   return proxyClass;
119 }
120 
121 }  // namespace proxy_test
122 }  // namespace art
123 
124 #endif  // ART_RUNTIME_PROXY_TEST_H_
125