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"