blob: fa5a449e31222e3a91f937eb07d611cbc2fe14c6 [file] [log] [blame]
David Brazdil1f9d3c32018-05-02 16:53:06 +01001/*
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"
Vladimir Marko679730e2018-05-25 15:06:48 +010025#include "class_root.h"
David Brazdil1f9d3c32018-05-02 16:53:06 +010026#include "mirror/class-inl.h"
27#include "mirror/method.h"
28
29namespace art {
30namespace proxy_test {
31
32// Generate a proxy class with the given name and interfaces. This is a simplification from what
33// libcore does to fit to our test needs. We do not check for duplicated interfaces or methods and
34// we do not declare exceptions.
35mirror::Class* GenerateProxyClass(ScopedObjectAccess& soa,
36 jobject jclass_loader,
37 ClassLinker* class_linker,
38 const char* className,
39 const std::vector<mirror::Class*>& interfaces)
40 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markoe9987b02018-05-22 16:26:43 +010041 StackHandleScope<1> hs(soa.Self());
42 Handle<mirror::Class> javaLangObject = hs.NewHandle(
43 class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;"));
David Brazdil1f9d3c32018-05-02 16:53:06 +010044 CHECK(javaLangObject != nullptr);
45
46 jclass javaLangClass = soa.AddLocalReference<jclass>(mirror::Class::GetJavaLangClass());
47
48 // Builds the interfaces array.
49 jobjectArray proxyClassInterfaces = soa.Env()->NewObjectArray(interfaces.size(), javaLangClass,
50 nullptr);
51 soa.Self()->AssertNoPendingException();
52 for (size_t i = 0; i < interfaces.size(); ++i) {
53 soa.Env()->SetObjectArrayElement(proxyClassInterfaces, i,
54 soa.AddLocalReference<jclass>(interfaces[i]));
55 }
56
57 // Builds the method array.
58 jsize methods_count = 3; // Object.equals, Object.hashCode and Object.toString.
59 for (mirror::Class* interface : interfaces) {
60 methods_count += interface->NumVirtualMethods();
61 }
62 jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(
Vladimir Marko679730e2018-05-25 15:06:48 +010063 methods_count, soa.AddLocalReference<jclass>(GetClassRoot<mirror::Method>()), nullptr);
David Brazdil1f9d3c32018-05-02 16:53:06 +010064 soa.Self()->AssertNoPendingException();
65
66 jsize array_index = 0;
67 // Fill the method array
68 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
69 ArtMethod* method = javaLangObject->FindClassMethod(
70 "equals", "(Ljava/lang/Object;)Z", kRuntimePointerSize);
71 CHECK(method != nullptr);
72 CHECK(!method->IsDirect());
Vladimir Markoe9987b02018-05-22 16:26:43 +010073 CHECK(method->GetDeclaringClass() == javaLangObject.Get());
David Brazdil1f9d3c32018-05-02 16:53:06 +010074 DCHECK(!Runtime::Current()->IsActiveTransaction());
75 soa.Env()->SetObjectArrayElement(
76 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
77 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
78 method = javaLangObject->FindClassMethod("hashCode", "()I", kRuntimePointerSize);
79 CHECK(method != nullptr);
80 CHECK(!method->IsDirect());
Vladimir Markoe9987b02018-05-22 16:26:43 +010081 CHECK(method->GetDeclaringClass() == javaLangObject.Get());
David Brazdil1f9d3c32018-05-02 16:53:06 +010082 soa.Env()->SetObjectArrayElement(
83 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
84 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
85 method = javaLangObject->FindClassMethod(
86 "toString", "()Ljava/lang/String;", kRuntimePointerSize);
87 CHECK(method != nullptr);
88 CHECK(!method->IsDirect());
Vladimir Markoe9987b02018-05-22 16:26:43 +010089 CHECK(method->GetDeclaringClass() == javaLangObject.Get());
David Brazdil1f9d3c32018-05-02 16:53:06 +010090 soa.Env()->SetObjectArrayElement(
91 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
92 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
93 // Now adds all interfaces virtual methods.
94 for (mirror::Class* interface : interfaces) {
95 for (auto& m : interface->GetDeclaredVirtualMethods(kRuntimePointerSize)) {
96 soa.Env()->SetObjectArrayElement(
97 proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
98 mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), &m)));
99 }
100 }
101 CHECK_EQ(array_index, methods_count);
102
103 // Builds an empty exception array.
104 jobjectArray proxyClassThrows = soa.Env()->NewObjectArray(0, javaLangClass, nullptr);
105 soa.Self()->AssertNoPendingException();
106
107 mirror::Class* proxyClass = class_linker->CreateProxyClass(
108 soa, soa.Env()->NewStringUTF(className), proxyClassInterfaces, jclass_loader,
109 proxyClassMethods, proxyClassThrows);
110 soa.Self()->AssertNoPendingException();
111 return proxyClass;
112}
113
114} // namespace proxy_test
115} // namespace art
116
117#endif // ART_RUNTIME_PROXY_TEST_H_