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-current-inl.h" 43 44 namespace 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 50 jvmtiError 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 122 jvmtiError 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 145 jvmtiError 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 168 jvmtiError 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 jvmtiError FieldUtil::SetFieldModificationWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) { 191 ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv); 192 if (klass == nullptr) { 193 return ERR(INVALID_CLASS); 194 } 195 if (field == nullptr) { 196 return ERR(INVALID_FIELDID); 197 } 198 auto res_pair = env->modify_watched_fields.insert(art::jni::DecodeArtField(field)); 199 if (!res_pair.second) { 200 // Didn't get inserted because it's already present! 201 return ERR(DUPLICATE); 202 } 203 return OK; 204 } 205 206 jvmtiError FieldUtil::ClearFieldModificationWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) { 207 ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv); 208 if (klass == nullptr) { 209 return ERR(INVALID_CLASS); 210 } 211 if (field == nullptr) { 212 return ERR(INVALID_FIELDID); 213 } 214 auto pos = env->modify_watched_fields.find(art::jni::DecodeArtField(field)); 215 if (pos == env->modify_watched_fields.end()) { 216 return ERR(NOT_FOUND); 217 } 218 env->modify_watched_fields.erase(pos); 219 return OK; 220 } 221 222 jvmtiError FieldUtil::SetFieldAccessWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) { 223 ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv); 224 if (klass == nullptr) { 225 return ERR(INVALID_CLASS); 226 } 227 if (field == nullptr) { 228 return ERR(INVALID_FIELDID); 229 } 230 auto res_pair = env->access_watched_fields.insert(art::jni::DecodeArtField(field)); 231 if (!res_pair.second) { 232 // Didn't get inserted because it's already present! 233 return ERR(DUPLICATE); 234 } 235 return OK; 236 } 237 238 jvmtiError FieldUtil::ClearFieldAccessWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) { 239 ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv); 240 if (klass == nullptr) { 241 return ERR(INVALID_CLASS); 242 } 243 if (field == nullptr) { 244 return ERR(INVALID_FIELDID); 245 } 246 auto pos = env->access_watched_fields.find(art::jni::DecodeArtField(field)); 247 if (pos == env->access_watched_fields.end()) { 248 return ERR(NOT_FOUND); 249 } 250 env->access_watched_fields.erase(pos); 251 return OK; 252 } 253 254 } // namespace openjdkjvmti 255