1 /* 2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/javaClasses.hpp" 27 #include "classfile/symbolTable.hpp" 28 #include "classfile/systemDictionary.hpp" 29 #include "jfr/jni/jfrJavaSupport.hpp" 30 #include "jfr/jni/jfrUpcalls.hpp" 31 #include "jfr/support/jfrEventClass.hpp" 32 #include "memory/oopFactory.hpp" 33 #include "oops/oop.inline.hpp" 34 #include "oops/typeArrayKlass.hpp" 35 #include "oops/typeArrayOop.hpp" 36 #include "runtime/handles.inline.hpp" 37 #include "runtime/os.hpp" 38 #include "runtime/thread.inline.hpp" 39 #include "utilities/exceptions.hpp" 40 41 static Symbol* jvm_upcalls_class_sym = NULL; 42 static Symbol* on_retransform_method_sym = NULL; 43 static Symbol* on_retransform_signature_sym = NULL; 44 static Symbol* bytes_for_eager_instrumentation_sym = NULL; 45 static Symbol* bytes_for_eager_instrumentation_sig_sym = NULL; 46 47 static bool initialize(TRAPS) { 48 static bool initialized = false; 49 if (!initialized) { 50 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 51 jvm_upcalls_class_sym = SymbolTable::new_permanent_symbol("jdk/jfr/internal/JVMUpcalls", CHECK_false); 52 on_retransform_method_sym = SymbolTable::new_permanent_symbol("onRetransform", CHECK_false); 53 on_retransform_signature_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B", CHECK_false); 54 bytes_for_eager_instrumentation_sym = SymbolTable::new_permanent_symbol("bytesForEagerInstrumentation", CHECK_false); 55 bytes_for_eager_instrumentation_sig_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B", THREAD); 56 initialized = bytes_for_eager_instrumentation_sig_sym != NULL; 57 } 58 return initialized; 59 } 60 61 static const typeArrayOop invoke(jlong trace_id, 62 jboolean force_instrumentation, 63 jclass class_being_redefined, 64 jint class_data_len, 65 const unsigned char* class_data, 66 Symbol* method_sym, 67 Symbol* signature_sym, 68 jint& new_bytes_length, 69 TRAPS) { 70 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 71 const Klass* klass = SystemDictionary::resolve_or_fail(jvm_upcalls_class_sym, true, CHECK_NULL); 72 assert(klass != NULL, "invariant"); 73 typeArrayOop old_byte_array = oopFactory::new_byteArray(class_data_len, CHECK_NULL); 74 memcpy(old_byte_array->byte_at_addr(0), class_data, class_data_len); 75 JavaValue result(T_OBJECT); 76 JfrJavaArguments args(&result, klass, method_sym, signature_sym); 77 args.push_long(trace_id); 78 args.push_int(force_instrumentation); 79 args.push_jobject(class_being_redefined); 80 args.push_oop(old_byte_array); 81 JfrJavaSupport::call_static(&args, THREAD); 82 if (HAS_PENDING_EXCEPTION) { 83 if (true) tty->print_cr("JfrUpcall failed"); 84 return NULL; 85 } 86 // The result should be a [B 87 const oop res = (oop)result.get_jobject(); 88 assert(res != NULL, "invariant"); 89 assert(res->is_typeArray(), "invariant"); 90 assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "invariant"); 91 const typeArrayOop new_byte_array = typeArrayOop(res); 92 new_bytes_length = (jint)new_byte_array->length(); 93 return new_byte_array; 94 } 95 96 static const size_t ERROR_MSG_BUFFER_SIZE = 256; 97 static void log_error_and_throw_oom(jint new_bytes_length, TRAPS) { 98 char error_buffer[ERROR_MSG_BUFFER_SIZE]; 99 jio_snprintf(error_buffer, ERROR_MSG_BUFFER_SIZE, 100 "Thread local allocation (native) for " SIZE_FORMAT " bytes failed in JfrUpcalls", (size_t)new_bytes_length); 101 if (true) tty->print_cr("%s", error_buffer); 102 JfrJavaSupport::throw_out_of_memory_error(error_buffer, CHECK); 103 } 104 105 void JfrUpcalls::on_retransform(jlong trace_id, 106 jclass class_being_redefined, 107 jint class_data_len, 108 const unsigned char* class_data, 109 jint* new_class_data_len, 110 unsigned char** new_class_data, 111 TRAPS) { 112 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 113 assert(class_being_redefined != NULL, "invariant"); 114 assert(class_data != NULL, "invariant"); 115 assert(new_class_data_len != NULL, "invariant"); 116 assert(new_class_data != NULL, "invariant"); 117 if (!JdkJfrEvent::is_visible(class_being_redefined)) { 118 return; 119 } 120 jint new_bytes_length = 0; 121 initialize(THREAD); 122 const typeArrayOop new_byte_array = invoke(trace_id, 123 false, 124 class_being_redefined, 125 class_data_len, 126 class_data, 127 on_retransform_method_sym, 128 on_retransform_signature_sym, 129 new_bytes_length, 130 CHECK); 131 assert(new_byte_array != NULL, "invariant"); 132 assert(new_bytes_length > 0, "invariant"); 133 // memory space must be malloced as mtInternal 134 // as it will be deallocated by JVMTI routines 135 unsigned char* const new_bytes = (unsigned char* const)os::malloc(new_bytes_length, mtInternal); 136 if (new_bytes == NULL) { 137 log_error_and_throw_oom(new_bytes_length, THREAD); // unwinds 138 } 139 assert(new_bytes != NULL, "invariant"); 140 memcpy(new_bytes, new_byte_array->byte_at_addr(0), (size_t)new_bytes_length); 141 *new_class_data_len = new_bytes_length; 142 *new_class_data = new_bytes; 143 } 144 145 void JfrUpcalls::new_bytes_eager_instrumentation(jlong trace_id, 146 jboolean force_instrumentation, 147 jclass super, 148 jint class_data_len, 149 const unsigned char* class_data, 150 jint* new_class_data_len, 151 unsigned char** new_class_data, 152 TRAPS) { 153 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 154 assert(super != NULL, "invariant"); 155 assert(class_data != NULL, "invariant"); 156 assert(new_class_data_len != NULL, "invariant"); 157 assert(new_class_data != NULL, "invariant"); 158 jint new_bytes_length = 0; 159 initialize(THREAD); 160 const typeArrayOop new_byte_array = invoke(trace_id, 161 force_instrumentation, 162 super, 163 class_data_len, 164 class_data, 165 bytes_for_eager_instrumentation_sym, 166 bytes_for_eager_instrumentation_sig_sym, 167 new_bytes_length, 168 CHECK); 169 assert(new_byte_array != NULL, "invariant"); 170 assert(new_bytes_length > 0, "invariant"); 171 unsigned char* const new_bytes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, unsigned char, new_bytes_length); 172 if (new_bytes == NULL) { 173 log_error_and_throw_oom(new_bytes_length, THREAD); // this unwinds 174 } 175 assert(new_bytes != NULL, "invariant"); 176 memcpy(new_bytes, new_byte_array->byte_at_addr(0), (size_t)new_bytes_length); 177 *new_class_data_len = new_bytes_length; 178 *new_class_data = new_bytes; 179 }