1 /*
  2  * Copyright (c) 2026, 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 #include <string.h>
 25 #include "jvmti.h"
 26 #include "jvmti_common.hpp"
 27 
 28 extern "C" {
 29 
 30 static jvmtiEnv *jvmti = nullptr;
 31 static jrawMonitorID event_mon = nullptr;
 32 
 33 static int number_of_allocation = 0;
 34 
 35 extern JNIEXPORT void JNICALL
 36 VMObjectAlloc(jvmtiEnv *jvmti,
 37               JNIEnv* jni,
 38               jthread thread,
 39               jobject object,
 40               jclass cls,
 41               jlong size) {
 42   RawMonitorLocker locker(jvmti, jni, event_mon);
 43 
 44   char *sig = nullptr;
 45   jvmtiError err = jvmti->GetClassSignature(cls, &sig, nullptr);
 46   if (err != JVMTI_ERROR_NONE) {
 47     jni->FatalError("Failed during the GetClassSignature call");
 48   }
 49 
 50   if (strcmp(sig, "LVMObjectAllocValueTest;") == 0) {
 51     LOG("VMObjectAlloc called for %s obj: %p\n", sig, (void*)object);
 52     number_of_allocation++;
 53     if (object != nullptr) {
 54       fatal(jni, "Failed: object parameter for value object alloc is expected to be nullptr");
 55     }
 56   }
 57   jvmti->Deallocate((unsigned char *)sig);
 58 }
 59 
 60 static void JNICALL
 61 VMDeath(jvmtiEnv *jvmti, JNIEnv* jni) {
 62   RawMonitorLocker locker(jvmti, jni, event_mon);
 63 
 64   LOG("VMDeath\n");
 65 }
 66 
 67 JNIEXPORT jint JNICALL
 68 Java_VMObjectAllocValueTest_getNumberOfAllocation(JNIEnv *env, jclass cls) {
 69   return number_of_allocation;
 70 }
 71 
 72 extern JNIEXPORT jint JNICALL
 73 Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
 74   jvmtiEventCallbacks callbacks;
 75   jvmtiError err;
 76   jvmtiCapabilities caps;
 77 
 78   if (jvm->GetEnv((void **) &jvmti, JVMTI_VERSION) != JNI_OK) {
 79     return JNI_ERR;
 80   }
 81 
 82   err = jvmti->CreateRawMonitor("Event Monitor", &event_mon);
 83   if (err != JVMTI_ERROR_NONE) {
 84     LOG("Agent_OnLoad: CreateRawMonitor failed: %d\n", err);
 85     return JNI_ERR;
 86   }
 87 
 88   memset(&callbacks, 0, sizeof(callbacks));
 89   callbacks.VMObjectAlloc = &VMObjectAlloc;
 90   callbacks.VMDeath = &VMDeath;
 91   memset(&caps, 0, sizeof(caps));
 92   caps.can_generate_vm_object_alloc_events = 1;
 93 
 94   err = jvmti->AddCapabilities( &caps);
 95   if (err != JVMTI_ERROR_NONE) {
 96     return JNI_ERR;
 97   }
 98 
 99   err = jvmti->SetEventCallbacks(&callbacks, sizeof(jvmtiEventCallbacks));
100   if (err != JVMTI_ERROR_NONE) {
101     return JNI_ERR;
102   }
103 
104   err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC , nullptr);
105   if (err != JVMTI_ERROR_NONE) {
106     return JNI_ERR;
107   }
108   err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, nullptr);
109   if (err != JVMTI_ERROR_NONE) {
110     return JNI_ERR;
111   }
112 
113   return JNI_OK;
114 }
115 
116 } //extern "C"