Skip to content

Commit 4c23fa5

Browse files
committed
WIP
1 parent da36470 commit 4c23fa5

File tree

11 files changed

+543
-124
lines changed

11 files changed

+543
-124
lines changed

ddprof-lib/src/main/cpp/javaApi.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,95 @@ Java_com_datadoghq_profiler_JavaProfiler_mallocArenaMax0(JNIEnv *env,
283283
jint maxArenas) {
284284
OS::mallocArenaMax(maxArenas);
285285
}
286+
287+
288+
// JVM Flags
289+
// The flag type is encoded as:
290+
// 0 - boolean
291+
// 1 - int
292+
// 2 - uint
293+
// 3 - intx
294+
// 4 - uintx
295+
// 5 - uint64_t
296+
// 6 - size_t
297+
// 7 - double
298+
// 8 - string
299+
// 9 - string list
300+
extern "C" DLLEXPORT jstring JNICALL
301+
Java_com_datadoghq_profiler_JVMAccess_findStringJVMFlag0(JNIEnv *env,
302+
jobject unused,
303+
jstring flagName) {
304+
JniString flag_str(env, flagName);
305+
char** value = static_cast<char**>(JVMFlag::find(flag_str.c_str(), 256)); // types: 2 ^ [8]
306+
if (value != NULL && *value != NULL) {
307+
return env->NewStringUTF(*value);
308+
}
309+
return NULL;
310+
}
311+
312+
extern "C" DLLEXPORT void JNICALL
313+
Java_com_datadoghq_profiler_JVMAccess_setStringJVMFlag0(JNIEnv *env,
314+
jobject unused,
315+
jstring flagName,
316+
jstring flagValue) {
317+
JniString flag_str(env, flagName);
318+
JniString value_str(env, flagValue);
319+
char** value = static_cast<char**>(JVMFlag::find(flag_str.c_str(), 256)); // types: 2 ^ [8]
320+
if (value != NULL) {
321+
*value = strdup(value_str.c_str());
322+
}
323+
}
324+
325+
extern "C" DLLEXPORT jboolean JNICALL
326+
Java_com_datadoghq_profiler_JVMAccess_findBooleanJVMFlag0(JNIEnv *env,
327+
jobject unused,
328+
jstring flagName) {
329+
JniString flag_str(env, flagName);
330+
char* value = static_cast<char*>(JVMFlag::find(flag_str.c_str(), 1)); // types: 2 ^ [0]
331+
if (value != NULL) {
332+
return *value == 1;
333+
}
334+
return false;
335+
}
336+
337+
extern "C" DLLEXPORT void JNICALL
338+
Java_com_datadoghq_profiler_JVMAccess_setBooleanJVMFlag0(JNIEnv *env,
339+
jobject unused,
340+
jstring flagName,
341+
jboolean flagValue) {
342+
JniString flag_str(env, flagName);
343+
char* value = static_cast<char*>(JVMFlag::find(flag_str.c_str(), 1)); // types: 2 ^ [0]
344+
if (value != NULL) {
345+
*value == flagValue ? 1 : 0;
346+
}
347+
}
348+
349+
extern "C" DLLEXPORT jlong JNICALL
350+
Java_com_datadoghq_profiler_JVMAccess_findIntJVMFlag0(JNIEnv *env,
351+
jobject unused,
352+
jstring flagName) {
353+
JniString flag_str(env, flagName);
354+
long* value = static_cast<long*>(JVMFlag::find(flag_str.c_str(), 126)); // types: 2 ^ [1, 2, 3, 4, 5, 6]
355+
if (value != NULL) {
356+
return *value;
357+
}
358+
return 0;
359+
}
360+
361+
extern "C" DLLEXPORT jdouble JNICALL
362+
Java_com_datadoghq_profiler_JVMAccess_findFloatJVMFlag0(JNIEnv *env,
363+
jobject unused,
364+
jstring flagName) {
365+
JniString flag_str(env, flagName);
366+
double* value = static_cast<double*>(JVMFlag::find(flag_str.c_str(), 128)); // types: 2 ^ [7]
367+
if (value != NULL) {
368+
return *value;
369+
}
370+
return 0.0;
371+
}
372+
373+
extern "C" DLLEXPORT jboolean JNICALL
374+
Java_com_datadoghq_profiler_JVMAccess_healthCheck0(JNIEnv *env,
375+
jobject unused) {
376+
return true;
377+
}

ddprof-lib/src/main/cpp/vmStructs.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ int VMStructs::_vs_low_bound_offset = -1;
8484
int VMStructs::_vs_high_bound_offset = -1;
8585
int VMStructs::_vs_low_offset = -1;
8686
int VMStructs::_vs_high_offset = -1;
87+
int VMStructs::_flag_type_offset = -1;
8788
int VMStructs::_flag_name_offset = -1;
8889
int VMStructs::_flag_addr_offset = -1;
8990
const char *VMStructs::_flags_addr = NULL;
@@ -321,7 +322,9 @@ void VMStructs::initOffsets() {
321322
_array_data_offset = *(int *)(entry + offset_offset);
322323
}
323324
} else if (strcmp(type, "JVMFlag") == 0 || strcmp(type, "Flag") == 0) {
324-
if (strcmp(field, "_name") == 0 || strcmp(field, "name") == 0) {
325+
if (strcmp(field, "_type") == 0 || strcmp(field, "type") == 0) {
326+
_flag_type_offset = *(int *)(entry + offset_offset);
327+
} else if (strcmp(field, "_name") == 0 || strcmp(field, "name") == 0) {
325328
_flag_name_offset = *(int *)(entry + offset_offset);
326329
} else if (strcmp(field, "_addr") == 0 || strcmp(field, "addr") == 0) {
327330
_flag_addr_offset = *(int *)(entry + offset_offset);
@@ -781,6 +784,21 @@ void *JVMFlag::find(const char *name) {
781784
return NULL;
782785
}
783786

787+
void *JVMFlag::find(const char *name, int type_mask) {
788+
if (_flags_addr != NULL && _flag_size > 0) {
789+
for (int i = 0; i < _flag_count; i++) {
790+
JVMFlag *f = (JVMFlag *)(_flags_addr + i * _flag_size);
791+
if (f->name() != NULL && strcmp(f->name(), name) == 0) {
792+
int masked = 0x1 << f->type();
793+
if (masked & type_mask) {
794+
return f->addr();
795+
}
796+
}
797+
}
798+
}
799+
return NULL;
800+
}
801+
784802
int NMethod::findScopeOffset(const void *pc) {
785803
intptr_t pc_offset = (const char *)pc - code();
786804
if (pc_offset < 0 || pc_offset > 0x7fffffff) {

ddprof-lib/src/main/cpp/vmStructs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class VMStructs {
9292
static int _vs_high_bound_offset;
9393
static int _vs_low_offset;
9494
static int _vs_high_offset;
95+
static int _flag_type_offset;
9596
static int _flag_name_offset;
9697
static int _flag_addr_offset;
9798
static const char *_flags_addr;
@@ -528,8 +529,10 @@ class CodeHeap : VMStructs {
528529
class JVMFlag : VMStructs {
529530
public:
530531
static void *find(const char *name);
532+
static void *find(const char *name, int type_mask);
531533

532534
const char *name() { return *(const char **)at(_flag_name_offset); }
535+
int type() { return *(int *)at(_flag_type_offset); }
533536

534537
void *addr() { return *(void **)at(_flag_addr_offset); }
535538
};
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package com.datadoghq.profiler;
2+
3+
import java.util.function.Consumer;
4+
5+
public final class JVMAccess {
6+
private static final class SingletonHolder {
7+
static final JVMAccess INSTANCE = new JVMAccess();
8+
}
9+
10+
public interface Flags {
11+
Flags NONE = new Flags() {
12+
@Override
13+
public String getStringFlag(String name) {
14+
return null;
15+
}
16+
17+
@Override
18+
public void setStringFlag(String name, String value) {
19+
}
20+
21+
@Override
22+
public boolean getBooleanFlag(String name) {
23+
return false;
24+
}
25+
26+
@Override
27+
public void setBooleanFlag(String name, boolean value) {
28+
}
29+
30+
@Override
31+
public long getIntFlag(String name) {
32+
return 0;
33+
}
34+
35+
@Override
36+
public double getFloatFlag(String name) {
37+
return 0;
38+
}
39+
};
40+
41+
String getStringFlag(String name);
42+
void setStringFlag(String name, String value);
43+
boolean getBooleanFlag(String name);
44+
void setBooleanFlag(String name, boolean value);
45+
long getIntFlag(String name);
46+
double getFloatFlag(String name);
47+
}
48+
49+
private class FlagsImpl implements Flags {
50+
public String getStringFlag(String name) {
51+
return findStringJVMFlag0(name);
52+
}
53+
54+
public void setStringFlag(String name, String value) {
55+
setStringJVMFlag0(name, value);
56+
}
57+
58+
public boolean getBooleanFlag(String name) {
59+
return findBooleanJVMFlag0(name);
60+
}
61+
62+
public void setBooleanFlag(String name, boolean value) {
63+
setBooleanJVMFlag0(name, value);
64+
}
65+
66+
public long getIntFlag(String name) {
67+
return findIntJVMFlag0(name);
68+
}
69+
70+
public double getFloatFlag(String name) {
71+
return findFloatJVMFlag0(name);
72+
}
73+
}
74+
75+
public static JVMAccess getInstance() {
76+
return SingletonHolder.INSTANCE;
77+
}
78+
79+
private final LibraryLoader.Result libraryLoadResult;
80+
private final Flags flags;
81+
82+
private JVMAccess() {
83+
LibraryLoader.Result result = LibraryLoader.builder().load();;
84+
if (result.success) {
85+
// library loaded successfully, check if we can access JVM
86+
try {
87+
healthCheck0();
88+
} catch (Throwable t) {
89+
// failed to access JVM; update the result
90+
result = new LibraryLoader.Result(false, t);
91+
}
92+
93+
}
94+
if (!result.success && result.error != null) {
95+
System.out.println("[WARNING] Failed to obtain JVM access.\n" + result.error);
96+
}
97+
flags = result.success ? new FlagsImpl() : Flags.NONE;
98+
libraryLoadResult = result;
99+
}
100+
101+
public JVMAccess(String libLocation, String scratchDir, Consumer<Throwable> errorHandler) {
102+
LibraryLoader.Result result = LibraryLoader.builder().withLibraryLocation(libLocation).withScratchDir(scratchDir).load();
103+
if (result.success) {
104+
// library loaded successfully, check if we can access JVM
105+
try {
106+
healthCheck0();
107+
} catch (Throwable t) {
108+
// failed to access JVM; update the result
109+
result = new LibraryLoader.Result(false, t);
110+
}
111+
112+
}
113+
if (!result.success && result.error != null) {
114+
if (errorHandler != null) {
115+
errorHandler.accept(result.error);
116+
} else {
117+
System.out.println("[WARNING] Failed to obtain JVM access.\n" + result.error);
118+
}
119+
}
120+
flags = result.success ? new FlagsImpl() : Flags.NONE;
121+
libraryLoadResult = result;
122+
}
123+
124+
public Flags flags() {
125+
return flags;
126+
}
127+
128+
public boolean isActive() {
129+
return libraryLoadResult.success;
130+
}
131+
132+
// a dummy method to check if the library has loaded properly
133+
private native boolean healthCheck0();
134+
135+
private native String findStringJVMFlag0(String name);
136+
private native void setStringJVMFlag0(String name, String value);
137+
private native boolean findBooleanJVMFlag0(String name);
138+
private native void setBooleanJVMFlag0(String name, boolean value);
139+
private native long findIntJVMFlag0(String name);
140+
private native double findFloatJVMFlag0(String name);
141+
}

0 commit comments

Comments
 (0)