1/* Copyright (C) 2016 The Android Open Source Project 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This file implements interfaces from the file jvmti.h. This implementation 5 * is licensed under the same terms as the file jvmti.h. The 6 * copyright and license information for the file jvmti.h follows. 7 * 8 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10 * 11 * This code is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License version 2 only, as 13 * published by the Free Software Foundation. Oracle designates this 14 * particular file as subject to the "Classpath" exception as provided 15 * by Oracle in the LICENSE file that accompanied this code. 16 * 17 * This code is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20 * version 2 for more details (a copy is included in the LICENSE file that 21 * accompanied this code). 22 * 23 * You should have received a copy of the GNU General Public License version 24 * 2 along with this work; if not, write to the Free Software Foundation, 25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26 * 27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 28 * or visit www.oracle.com if you need additional information or have any 29 * questions. 30 */ 31 32#include "ti_field.h" 33 34#include "art_jvmti.h" 35#include "art_field-inl.h" 36#include "base/enums.h" 37#include "dex_file_annotations.h" 38#include "jni_internal.h" 39#include "mirror/object_array-inl.h" 40#include "modifiers.h" 41#include "scoped_thread_state_change-inl.h" 42#include "thread-inl.h" 43 44namespace openjdkjvmti { 45 46// Note: For all these functions, we could do a check that the field actually belongs to the given 47// class. But the spec seems to assume a certain encoding of the field ID, and so doesn't 48// specify any errors. 49 50jvmtiError FieldUtil::GetFieldName(jvmtiEnv* env, 51 jclass klass, 52 jfieldID field, 53 char** name_ptr, 54 char** signature_ptr, 55 char** generic_ptr) { 56 if (klass == nullptr) { 57 return ERR(INVALID_CLASS); 58 } 59 if (field == nullptr) { 60 return ERR(INVALID_FIELDID); 61 } 62 63 art::ScopedObjectAccess soa(art::Thread::Current()); 64 art::ArtField* art_field = art::jni::DecodeArtField(field); 65 66 JvmtiUniquePtr<char[]> name_copy; 67 if (name_ptr != nullptr) { 68 const char* field_name = art_field->GetName(); 69 if (field_name == nullptr) { 70 field_name = "<error>"; 71 } 72 jvmtiError ret; 73 name_copy = CopyString(env, field_name, &ret); 74 if (name_copy == nullptr) { 75 return ret; 76 } 77 *name_ptr = name_copy.get(); 78 } 79 80 JvmtiUniquePtr<char[]> signature_copy; 81 if (signature_ptr != nullptr) { 82 const char* sig = art_field->GetTypeDescriptor(); 83 jvmtiError ret; 84 signature_copy = CopyString(env, sig, &ret); 85 if (signature_copy == nullptr) { 86 return ret; 87 } 88 *signature_ptr = signature_copy.get(); 89 } 90 91 if (generic_ptr != nullptr) { 92 *generic_ptr = nullptr; 93 if (!art_field->GetDeclaringClass()->IsProxyClass()) { 94 art::mirror::ObjectArray<art::mirror::String>* str_array = 95 art::annotations::GetSignatureAnnotationForField(art_field); 96 if (str_array != nullptr) { 97 std::ostringstream oss; 98 for (int32_t i = 0; i != str_array->GetLength(); ++i) { 99 oss << str_array->Get(i)->ToModifiedUtf8(); 100 } 101 std::string output_string = oss.str(); 102 jvmtiError ret; 103 JvmtiUniquePtr<char[]> copy = CopyString(env, output_string.c_str(), &ret); 104 if (copy == nullptr) { 105 return ret; 106 } 107 *generic_ptr = copy.release(); 108 } else if (soa.Self()->IsExceptionPending()) { 109 // TODO: Should we report an error here? 110 soa.Self()->ClearException(); 111 } 112 } 113 } 114 115 // Everything is fine, release the buffers. 116 name_copy.release(); 117 signature_copy.release(); 118 119 return ERR(NONE); 120} 121 122jvmtiError FieldUtil::GetFieldDeclaringClass(jvmtiEnv* env ATTRIBUTE_UNUSED, 123 jclass klass, 124 jfieldID field, 125 jclass* declaring_class_ptr) { 126 if (klass == nullptr) { 127 return ERR(INVALID_CLASS); 128 } 129 if (field == nullptr) { 130 return ERR(INVALID_FIELDID); 131 } 132 if (declaring_class_ptr == nullptr) { 133 return ERR(NULL_POINTER); 134 } 135 136 art::ScopedObjectAccess soa(art::Thread::Current()); 137 art::ArtField* art_field = art::jni::DecodeArtField(field); 138 art::ObjPtr<art::mirror::Class> field_klass = art_field->GetDeclaringClass(); 139 140 *declaring_class_ptr = soa.AddLocalReference<jclass>(field_klass); 141 142 return ERR(NONE); 143} 144 145jvmtiError FieldUtil::GetFieldModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED, 146 jclass klass, 147 jfieldID field, 148 jint* modifiers_ptr) { 149 if (klass == nullptr) { 150 return ERR(INVALID_CLASS); 151 } 152 if (field == nullptr) { 153 return ERR(INVALID_FIELDID); 154 } 155 if (modifiers_ptr == nullptr) { 156 return ERR(NULL_POINTER); 157 } 158 159 art::ScopedObjectAccess soa(art::Thread::Current()); 160 art::ArtField* art_field = art::jni::DecodeArtField(field); 161 // Note: Keep this code in sync with Field.getModifiers. 162 uint32_t modifiers = art_field->GetAccessFlags() & 0xFFFF; 163 164 *modifiers_ptr = modifiers; 165 return ERR(NONE); 166} 167 168jvmtiError FieldUtil::IsFieldSynthetic(jvmtiEnv* env ATTRIBUTE_UNUSED, 169 jclass klass, 170 jfieldID field, 171 jboolean* is_synthetic_ptr) { 172 if (klass == nullptr) { 173 return ERR(INVALID_CLASS); 174 } 175 if (field == nullptr) { 176 return ERR(INVALID_FIELDID); 177 } 178 if (is_synthetic_ptr == nullptr) { 179 return ERR(NULL_POINTER); 180 } 181 182 art::ScopedObjectAccess soa(art::Thread::Current()); 183 art::ArtField* art_field = art::jni::DecodeArtField(field); 184 uint32_t modifiers = art_field->GetAccessFlags(); 185 186 *is_synthetic_ptr = ((modifiers & art::kAccSynthetic) != 0) ? JNI_TRUE : JNI_FALSE; 187 return ERR(NONE); 188} 189 190} // namespace openjdkjvmti 191