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