xref: /illumos-gate/usr/src/lib/libdtrace_jni/common/dtj_util.h (revision 5d9d9091f564c198a760790b0bfa72c44e17912b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_DTJ_UTIL_H
28 #define	_DTJ_UTIL_H
29 
30 #include <jni.h>
31 #include <libuutil.h>
32 
33 #ifdef	__cplusplus
34 extern "C" {
35 #endif
36 
37 /*
38  * dtj_util.h separates functionality that is generally useful from
39  * that which is specific to the Java DTrace API.  If moved to a separate
40  * library, this functionality could be shared by other JNI wrappers.
41  */
42 
43 #ifdef JNI_VERSION_1_4
44 #define	JNI_VERSION JNI_VERSION_1_4
45 #else
46 #define	JNI_VERSION JNI_VERSION_1_2
47 #endif
48 
49 #define	CONSTRUCTOR "<init>"
50 #define	DTJ_MSG_SIZE 1024
51 #define	DTJ_INVALID_PTR ((void *)-1)
52 #define	DTJ_INVALID_STR ((const char *)-1)
53 
54 #define	WRAP_EXCEPTION(JENV)	dtj_wrap_exception((JENV), __FILE__, __LINE__)
55 
56 extern boolean_t g_dtj_util_debug;
57 
58 typedef enum dtj_status {
59 	DTJ_OK = JNI_OK,
60 	DTJ_ERR = JNI_ERR
61 } dtj_status_t;
62 
63 typedef enum dtj_type {
64 	JCLASS,
65 	JMETHOD,
66 	JMETHOD_STATIC,
67 	JFIELD,
68 	JFIELD_STATIC,
69 	DTJ_TYPE_END = -1
70 } dtj_type_t;
71 
72 /*
73  * Convenient description format for java classes, methods, and fields.  The
74  * java_class_t, java_method_t, and java_field_t structures derived from these
75  * descriptions are used to create a table of usable JNI jclass, jmethodID, and
76  * jfieldID instances.
77  */
78 typedef struct dtj_table_entry {
79 	dtj_type_t djte_type;	/* JNI type */
80 	void *djte_addr;	/* jclass, jmethodID, or jfieldID address */
81 	char *djte_name;	/* symbol name declared in Java */
82 	char *djte_desc;	/* JNI descriptor (string format) */
83 } dtj_table_entry_t;
84 
85 typedef struct dtj_java_class {
86 	jclass *djc_ptr;	/* address in user-defined structure */
87 	char *djc_name;		/* fully qualified '/' delimited class name */
88 	uu_list_t *djc_methods;	/* element type (java_method_t *) */
89 	uu_list_t *djc_fields;	/* element type (java_field_t *) */
90 	uu_list_node_t djc_node;
91 } dtj_java_class_t;
92 
93 typedef struct dtj_java_method {
94 	jmethodID *djm_ptr;	/* address in user-defined structure */
95 	char *djm_name;		/* method name in java source file */
96 	char *djm_signature;	/* javap -s method signature string */
97 	boolean_t djm_static;	/* flag indicating static qualifier */
98 	uu_list_node_t djm_node;
99 } dtj_java_method_t;
100 
101 typedef struct dtj_java_field {
102 	jfieldID *djf_ptr;	/* address in user-defined structure */
103 	char *djf_name;		/* field name in java source file */
104 	char *djf_type;		/* javap -s field type string */
105 	boolean_t djf_static;	/* flag indicating static qualifier */
106 	uu_list_node_t djf_node;
107 } dtj_java_field_t;
108 
109 /*
110  * Table of cached jclass, jmethodID, and jfieldID values usable across multiple
111  * native method calls and multiple threads.
112  *
113  * Suffix conventions:
114  *   jc  java class
115  *   jm  java method
116  *   jsm java static method
117  *   jf  java field
118  *   jsf java static field
119  */
120 
121 /* NativeException */
122 extern jclass g_nx_jc;
123 extern jmethodID g_nxinit_jm;
124 
125 /* java.io.Serializable */
126 extern jclass g_serial_jc;
127 
128 /* java.lang.Number */
129 extern jclass g_number_jc;
130 extern jmethodID g_shortval_jm;
131 extern jmethodID g_intval_jm;
132 extern jmethodID g_longval_jm;
133 
134 /* java.lang.Byte */
135 extern jclass g_byte_jc;
136 extern jmethodID g_byteinit_jm;
137 
138 /* java.lang.Character */
139 extern jclass g_char_jc;
140 extern jmethodID g_charinit_jm;
141 extern jmethodID g_charval_jm;
142 
143 /* java.lang.Short */
144 extern jclass g_short_jc;
145 extern jmethodID g_shortinit_jm;
146 
147 /* java.lang.Integer */
148 extern jclass g_int_jc;
149 extern jmethodID g_intinit_jm;
150 
151 /* java.lang.Long */
152 extern jclass g_long_jc;
153 extern jmethodID g_longinit_jm;
154 
155 /* java.math.BigInteger */
156 extern jclass g_bigint_jc;
157 extern jmethodID g_bigint_val_jsm;
158 extern jmethodID g_bigint_div_jm;
159 extern jmethodID g_bigint_shl_jm;
160 extern jmethodID g_bigint_or_jm;
161 extern jmethodID g_bigint_setbit_jm;
162 
163 /* java.lang.String */
164 extern jclass g_string_jc;
165 extern jmethodID g_strinit_bytes_jm;
166 extern jmethodID g_strbytes_jm;
167 extern jmethodID g_trim_jm;
168 
169 /* java.lang.StringBuffer */
170 extern jclass g_buf_jc;
171 extern jmethodID g_bufinit_jm;
172 extern jmethodID g_buf_append_char_jm;
173 extern jmethodID g_buf_append_int_jm;
174 extern jmethodID g_buf_append_long_jm;
175 extern jmethodID g_buf_append_str_jm;
176 extern jmethodID g_buf_append_obj_jm;
177 extern jmethodID g_buflen_jm;
178 extern jmethodID g_bufsetlen_jm;
179 
180 /* java.lang.Object */
181 extern jclass g_object_jc;
182 extern jmethodID g_tostring_jm;
183 extern jmethodID g_equals_jm;
184 
185 /* java.lang.Enum */
186 extern jclass g_enum_jc;
187 extern jmethodID g_enumname_jm;
188 
189 /* List */
190 extern jclass g_list_jc;
191 extern jmethodID g_listclear_jm;
192 extern jmethodID g_listadd_jm;
193 extern jmethodID g_listget_jm;
194 extern jmethodID g_listsize_jm;
195 
196 /*
197  * Populates the common java class references and associated method and field
198  * IDs declared in this file (above) using the dtj_cache_jni_classes() method.
199  */
200 extern dtj_status_t dtj_load_common(JNIEnv *);
201 
202 /*
203  * Populates the user-declared java class references and associated method and
204  * field IDs described in the given table.  Because the class references are
205  * created as global JNI references, the method and field IDs remain valid
206  * across multiple native method calls and across multiple threads.
207  *
208  * This function assumes that the given table of java class, method, and field
209  * descriptions is terminated by an entry with DTJ_TYPE_END, and that the
210  * method and field descriptions immediately follow the description of their
211  * containing class.
212  *
213  * Throws NoClassDefFoundError, NoSuchMethodError, or NoSuchFieldError if any
214  * dtj_table_entry_t in common_jni_table.c is incorrect.
215  */
216 extern dtj_status_t dtj_cache_jni_classes(JNIEnv *, const dtj_table_entry_t *);
217 
218 /* Common utilities */
219 
220 /*
221  * The following functions each create a pending Java Error or Exception:
222  *
223  * OutOfMemoryError
224  * NullPointerException
225  * IllegalArgumentException
226  * IllegalStateException
227  * NoSuchElementException
228  * ClassCastException
229  * AssertionError
230  * org.opensolaris.os.dtrace.ResourceLimitException
231  *
232  * Control should be returned to Java immediately afterwards.
233  */
234 extern void dtj_throw_out_of_memory(JNIEnv *, const char *, ...);
235 extern void dtj_throw_null_pointer(JNIEnv *, const char *, ...);
236 extern void dtj_throw_illegal_argument(JNIEnv *, const char *, ...);
237 extern void dtj_throw_illegal_state(JNIEnv *, const char *, ...);
238 extern void dtj_throw_no_such_element(JNIEnv *, const char *, ...);
239 extern void dtj_throw_class_cast(JNIEnv *, const char *, ...);
240 extern void dtj_throw_assertion(JNIEnv *, const char *, ...);
241 extern void dtj_throw_resource_limit(JNIEnv *, const char *, ...);
242 
243 /*
244  * Attaches native filename and line number to the currently pending java
245  * exception, since that information is not present in the exception stack
246  * trace.
247  */
248 extern void dtj_wrap_exception(JNIEnv *, const char *, int);
249 
250 /*
251  * Calls the toString() method of the given object and prints the value to
252  * stdout (useful for debugging).  If an exception is thrown in this function,
253  * it is described on stdout and cleared.  It's guaranteed that no exception is
254  * pending when this function returns.
255  */
256 extern void dtj_print_object(JNIEnv *jenv, jobject obj);
257 
258 /*
259  * Gets a java.math.BigInteger representing a 64-bit unsigned integer.
260  */
261 extern jobject dtj_uint64(JNIEnv *jenv, uint64_t);
262 
263 /*
264  * Gets a java.math.BigInteger representing a 128-bit integer given as 64 high
265  * bits (1st arg) and 64 low bits (2nd arg).
266  */
267 extern jobject dtj_int128(JNIEnv *jenv, uint64_t, uint64_t);
268 
269 /*
270  * Gets a formatted String (local reference) from a format and a variable
271  * argument list of placeholder values.  Returns NULL if OutOfMemoryError is
272  * thrown.
273  */
274 extern jstring dtj_format_string(JNIEnv *jenv, const char *fmt, ...);
275 
276 /*
277  * Internationalization support.  These functions taken (not verbatim) from
278  * Section 8.2 of The Java Native Interface by Sheng Liang, The Java Series.
279  * Use these functions for locale-specific strings such as file names.
280  */
281 extern jstring dtj_NewStringNative(JNIEnv *jenv, const char *str);
282 extern char *dtj_GetStringNativeChars(JNIEnv *jenv, jstring jstr);
283 extern void dtj_ReleaseStringNativeChars(JNIEnv *jenv, jstring jstr,
284     const char *str);
285 
286 /*
287  * Converts the args array of main(String[] args) in Java into a native
288  * dynamically allocated array of strings.  The returned array must be
289  * deallocated by calling free_argv().  A java exception is pending if this
290  * function returns NULL (in that case, any allocations made up to the point of
291  * failure in get_argv() are automatically freed).
292  *
293  * Returns a NULL-terminated array that works with functions that expect a
294  * terminating NULL rather than relying on an element count.  The argc parameter
295  * is also overwritten with the number of returned array elements (not including
296  * the terminating NULL).
297  */
298 extern char **dtj_get_argv(JNIEnv *jenv, jobjectArray args, int *argc);
299 /*
300  * Tokenizes a command string to create a native dynamically allocated array of
301  * strings.  The first element of the returned array is assumed to be the name
302  * of the command, and subsequent elements are arguments to that command.
303  * Otherwise behaves exactly like get_argv() above, including requiring a
304  * subsequent call to free_argv() on the returned array.
305  * Throws NullPointerException if cmd is NULL.
306  * Throws IllegalArgumentException if cmd is empty.
307  */
308 extern char **dtj_make_argv(JNIEnv *jenv, jstring cmd, int *argc);
309 extern void dtj_free_argv(char **argv);
310 
311 
312 /* Wrappers for uu_list_t */
313 
314 /*
315  * List element destructor.
316  * params: node pointer, user arg (may be NULL)
317  */
318 typedef void dtj_value_destroy_f(void *, void *);
319 
320 /*
321  * uu_list_t generic entry type for pointers compared by pointer value, similar
322  * to Java's default Object.equals() implementation (referenced objects are
323  * equal only if they have the same address in memory).  Used with
324  * pointer_list_entry_cmp.
325  */
326 typedef struct dtj_pointer_list_entry {
327 	void *dple_ptr;
328 	uu_list_node_t dple_node;
329 } dtj_pointer_list_entry_t;
330 
331 typedef struct dtj_string_list_entry {
332 	char *dsle_value;
333 	uu_list_node_t dsle_node;
334 } dtj_string_list_entry_t;
335 
336 /* Comparison functions, uu_compare_fn_t signature */
337 extern int dtj_pointer_list_entry_cmp(const void *, const void *, void *);
338 extern int dtj_string_list_entry_cmp(const void *, const void *, void *);
339 
340 /* Constructors */
341 extern uu_list_t *dtj_pointer_list_create(void);
342 extern dtj_pointer_list_entry_t *dtj_pointer_list_entry_create(void *);
343 extern uu_list_t *dtj_string_list_create(void);
344 extern dtj_string_list_entry_t *dtj_string_list_entry_create(const char *);
345 
346 /* Destructors */
347 extern void dtj_pointer_list_entry_destroy(void *, dtj_value_destroy_f *,
348     void *);
349 extern void dtj_string_list_entry_destroy(void *, void *);
350 /*
351  * Convenience function destroys a uu_list_t and its values.
352  *
353  * param list: list to be destroyed, call is a no-op if list is NULL
354  * param value_destroy: optional destructor; if non-NULL, it is called on each
355  *	list value
356  * param arg: user argument to the optional destructor
357  */
358 extern void dtj_list_destroy(uu_list_t *, dtj_value_destroy_f *, void *);
359 extern void dtj_pointer_list_destroy(uu_list_t *, dtj_value_destroy_f *,
360     void *);
361 extern void dtj_string_list_destroy(uu_list_t *);
362 
363 /*
364  * Convenience functions clear a uu_list_t without destroying it.  Destroys all
365  * list elements and leaves the list empty.  The *_list_destroy() functions
366  * implicitly clear the list before destroying it.
367  */
368 extern void dtj_list_clear(uu_list_t *, dtj_value_destroy_f *, void *);
369 extern void dtj_pointer_list_clear(uu_list_t *, dtj_value_destroy_f *,
370     void *);
371 extern void dtj_string_list_clear(uu_list_t *);
372 
373 extern boolean_t dtj_list_empty(uu_list_t *);
374 /* Return B_TRUE if successful, B_FALSE otherwise */
375 extern boolean_t dtj_list_add(uu_list_t *, void *);
376 extern boolean_t dtj_pointer_list_add(uu_list_t *, void *);
377 extern boolean_t dtj_string_list_add(uu_list_t *, const char *);
378 /* Return INVALID_PTR if list is empty (NULL is a valid list element) */
379 extern void * dtj_pointer_list_first(uu_list_t *);
380 extern void * dtj_pointer_list_last(uu_list_t *);
381 /* Return INVALID_STR if list is empty (NULL is a valid list element) */
382 extern const char *dtj_string_list_first(uu_list_t *);
383 extern const char *dtj_string_list_last(uu_list_t *);
384 /* Return INVALID_PTR at end of list (NULL is a valid list element) */
385 extern void *dtj_pointer_list_walk_next(uu_list_walk_t *);
386 /* Return INVALID_STR at end of list (NULL is a valid list element) */
387 extern const char *dtj_string_list_walk_next(uu_list_walk_t *);
388 
389 #ifdef	__cplusplus
390 }
391 #endif
392 
393 #endif	/* _DTJ_UTIL_H */
394