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