xref: /illumos-gate/usr/src/lib/libdtrace_jni/common/dtj_consume.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <limits.h>
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <strings.h>
36 #include <sys/wait.h>
37 #include <limits.h>
38 #include <signal.h>
39 #include <libproc.h>
40 #include <pthread.h>
41 #include <dtrace_jni.h>
42 
43 /*
44  * Implements the work done in the running consumer loop.  The native Java
45  * methods (JNI layer) are implemented in dtrace_jni.c.
46  */
47 
48 /* Record handler passed to dtrace_work() */
49 static int dtj_chewrec(const dtrace_probedata_t *, const dtrace_recdesc_t *,
50     void *);
51 /* Probe data handler passed to dtrace_work() */
52 static int dtj_chew(const dtrace_probedata_t *, void *);
53 
54 /* Processes requests from LocalConsumer enqueued during dtrace_sleep() */
55 static dtj_status_t dtj_process_requests(dtj_java_consumer_t *);
56 
57 /*
58  * Callback handlers set in dtj_set_callback_handlers(), called from libdtrace
59  * in the consumer loop (from dtrace_work())
60  */
61 static int dtj_drophandler(const dtrace_dropdata_t *, void *);
62 static int dtj_errhandler(const dtrace_errdata_t *, void *);
63 static void dtj_prochandler(struct ps_prochandle *, const char *, void *);
64 static int dtj_setopthandler(const dtrace_setoptdata_t *, void *);
65 /*
66  * Buffered output handler called from libdtrace in both the consumer loop (from
67  * dtrace_work()) and the get_aggregate() function (from
68  * dtrace_aggregate_print()).
69  */
70 static int dtj_bufhandler(const dtrace_bufdata_t *, void *);
71 
72 /* Conversion of libdtrace data into Java Objects */
73 static jobject dtj_recdata(dtj_java_consumer_t *, uint32_t, caddr_t);
74 static jobject dtj_bytedata(JNIEnv *, uint32_t, caddr_t);
75 static jobject dtj_new_stack_record(const caddr_t, const dtrace_recdesc_t *,
76     dtj_java_consumer_t *);
77 static jobject dtj_new_probedata_stack_record(const dtrace_probedata_t *,
78     const dtrace_recdesc_t *, dtj_java_consumer_t *);
79 static jobject dtj_new_symbol_record(const caddr_t, const dtrace_recdesc_t *,
80     dtj_java_consumer_t *);
81 static jobject dtj_new_probedata_symbol_record(const dtrace_probedata_t *,
82     const dtrace_recdesc_t *, dtj_java_consumer_t *);
83 /* Aggregation data */
84 static jobject dtj_new_tuple_stack_record(const dtrace_aggdata_t *,
85     const dtrace_recdesc_t *, const char *, dtj_java_consumer_t *);
86 static jobject dtj_new_tuple_symbol_record(const dtrace_aggdata_t *,
87     const dtrace_recdesc_t *, const char *, dtj_java_consumer_t *);
88 static jobject dtj_new_distribution(const dtrace_aggdata_t *,
89     const dtrace_recdesc_t *, dtj_java_consumer_t *);
90 static jobject dtj_new_aggval(dtj_java_consumer_t *, const dtrace_aggdata_t *,
91     const dtrace_recdesc_t *);
92 static int64_t dtj_average(caddr_t, uint64_t);
93 static int64_t dtj_avg_total(caddr_t, uint64_t);
94 static int64_t dtj_avg_count(caddr_t);
95 static jobject dtj_stddev(JNIEnv *, caddr_t, uint64_t);
96 
97 /* Aggregation functions */
98 static void dtj_aggwalk_init(dtj_java_consumer_t *);
99 static int dtj_agghandler(const dtrace_bufdata_t *, dtj_java_consumer_t *);
100 static boolean_t dtj_is_included(const dtrace_aggdata_t *,
101     dtj_java_consumer_t *);
102 static void dtj_attach_frames(dtj_java_consumer_t *, jobject, jobjectArray);
103 static void dtj_attach_name(dtj_java_consumer_t *, jobject, jstring);
104 static boolean_t dtj_is_stack_action(dtrace_actkind_t);
105 static boolean_t dtj_is_symbol_action(dtrace_actkind_t);
106 static int dtj_clear(const dtrace_aggdata_t *, void *);
107 
108 /*
109  * The consumer loop needs to protect calls to libdtrace functions with a global
110  * lock.  JNI native method calls in dtrace_jni.c are already protected and do
111  * not need this function.
112  */
113 dtj_status_t
114 dtj_get_dtrace_error(dtj_java_consumer_t *jc, dtj_error_t *e)
115 {
116 	JNIEnv *jenv = jc->dtjj_jenv;
117 	dtrace_hdl_t *dtp = jc->dtjj_consumer->dtjc_dtp;
118 
119 	/* Must not call MonitorEnter with a pending exception */
120 	if ((*jenv)->ExceptionCheck(jenv)) {
121 		WRAP_EXCEPTION(jenv);
122 		return (DTJ_ERR);
123 	}
124 	/* Grab global lock */
125 	(*jenv)->MonitorEnter(jenv, g_caller_jc);
126 	if ((*jenv)->ExceptionCheck(jenv)) {
127 		WRAP_EXCEPTION(jenv);
128 		return (DTJ_ERR);
129 	}
130 	e->dtje_number = dtrace_errno(dtp);
131 	e->dtje_message = dtrace_errmsg(dtp, e->dtje_number);
132 	(*jenv)->MonitorExit(jenv, g_caller_jc);
133 	if ((*jenv)->ExceptionCheck(jenv)) {
134 		WRAP_EXCEPTION(jenv);
135 		return (DTJ_ERR);
136 	}
137 	return (DTJ_OK);
138 }
139 
140 /*
141  * Protected by global lock (LocalConsumer.class) that protects call to
142  * Java_org_opensolaris_os_dtrace_LocalConsumer__1go()
143  */
144 dtj_status_t
145 dtj_set_callback_handlers(dtj_java_consumer_t *jc)
146 {
147 	dtrace_hdl_t *dtp = jc->dtjj_consumer->dtjc_dtp;
148 	dtrace_optval_t optval;
149 
150 	if (dtrace_handle_buffered(dtp, &dtj_bufhandler, NULL) == -1) {
151 		dtj_throw_dtrace_exception(jc,
152 		    "failed to establish buffered handler: %s",
153 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
154 		return (DTJ_ERR);
155 	}
156 
157 	if (dtrace_handle_drop(dtp, &dtj_drophandler, NULL) == -1) {
158 		dtj_throw_dtrace_exception(jc,
159 		    "failed to establish drop handler: %s",
160 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
161 		return (DTJ_ERR);
162 	}
163 
164 	if (dtrace_handle_err(dtp, &dtj_errhandler, NULL) == -1) {
165 		dtj_throw_dtrace_exception(jc,
166 		    "failed to establish error handler: %s",
167 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
168 		return (DTJ_ERR);
169 	}
170 
171 	if (dtrace_handle_proc(dtp, &dtj_prochandler, NULL) == -1) {
172 		dtj_throw_dtrace_exception(jc,
173 		    "failed to establish proc handler: %s",
174 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
175 		return (DTJ_ERR);
176 	}
177 
178 	if (dtrace_getopt(dtp, "flowindent", &optval) == -1) {
179 		dtj_throw_dtrace_exception(jc,
180 		    "couldn't get option %s: %s", "flowindent",
181 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
182 		return (DTJ_ERR);
183 	}
184 
185 	jc->dtjj_consumer->dtjc_flow = (optval != DTRACEOPT_UNSET);
186 
187 	if (dtrace_handle_setopt(dtp, &dtj_setopthandler, NULL) == -1) {
188 		dtj_throw_dtrace_exception(jc,
189 		    "failed to establish setopt handler: %s",
190 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
191 		return (DTJ_ERR);
192 	}
193 
194 	return (DTJ_OK);
195 }
196 
197 static int
198 /* ARGSUSED */
199 dtj_drophandler(const dtrace_dropdata_t *data, void *arg)
200 {
201 	dtj_java_consumer_t *jc;
202 	JNIEnv *jenv;
203 
204 	const char *dropkind;
205 
206 	jstring msg = NULL;
207 	jstring kind = NULL;
208 	jobject drop = NULL;
209 
210 	jc = pthread_getspecific(g_dtj_consumer_key);
211 	jenv = jc->dtjj_jenv;
212 
213 	msg = dtj_NewStringNative(jenv, data->dtdda_msg);
214 	if ((*jenv)->ExceptionCheck(jenv)) {
215 		return (DTRACE_HANDLE_ABORT);
216 	}
217 	switch (data->dtdda_kind) {
218 	case DTRACEDROP_PRINCIPAL:
219 		dropkind = "PRINCIPAL";
220 		break;
221 	case DTRACEDROP_AGGREGATION:
222 		dropkind = "AGGREGATION";
223 		break;
224 	case DTRACEDROP_DYNAMIC:
225 		dropkind = "DYNAMIC";
226 		break;
227 	case DTRACEDROP_DYNRINSE:
228 		dropkind = "DYNRINSE";
229 		break;
230 	case DTRACEDROP_DYNDIRTY:
231 		dropkind = "DYNDIRTY";
232 		break;
233 	case DTRACEDROP_SPEC:
234 		dropkind = "SPEC";
235 		break;
236 	case DTRACEDROP_SPECBUSY:
237 		dropkind = "SPECBUSY";
238 		break;
239 	case DTRACEDROP_SPECUNAVAIL:
240 		dropkind = "SPECUNAVAIL";
241 		break;
242 	case DTRACEDROP_STKSTROVERFLOW:
243 		dropkind = "STKSTROVERFLOW";
244 		break;
245 	case DTRACEDROP_DBLERROR:
246 		dropkind = "DBLERROR";
247 		break;
248 	default:
249 		dropkind = "UNKNOWN";
250 	}
251 	kind = (*jenv)->NewStringUTF(jenv, dropkind);
252 	if ((*jenv)->ExceptionCheck(jenv)) {
253 		(*jenv)->DeleteLocalRef(jenv, msg);
254 		return (DTRACE_HANDLE_ABORT);
255 	}
256 	drop = (*jenv)->NewObject(jenv, g_drop_jc, g_dropinit_jm,
257 	    data->dtdda_cpu, kind, data->dtdda_drops, data->dtdda_total, msg);
258 	(*jenv)->DeleteLocalRef(jenv, kind);
259 	(*jenv)->DeleteLocalRef(jenv, msg);
260 	if ((*jenv)->ExceptionCheck(jenv)) {
261 		return (DTRACE_HANDLE_ABORT);
262 	}
263 	(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller, g_drop_jm, drop);
264 	(*jenv)->DeleteLocalRef(jenv, drop);
265 	if ((*jenv)->ExceptionCheck(jenv)) {
266 		return (DTRACE_HANDLE_ABORT);
267 	}
268 
269 	return (DTRACE_HANDLE_OK);
270 }
271 
272 static int
273 /* ARGSUSED */
274 dtj_errhandler(const dtrace_errdata_t *data, void *arg)
275 {
276 	dtj_java_consumer_t *jc;
277 	JNIEnv *jenv;
278 
279 	const char *f;
280 	int64_t addr;
281 
282 	jobject probe = NULL;
283 	jstring fault = NULL;
284 	jstring msg = NULL;
285 	jobject error = NULL;
286 
287 	jc = pthread_getspecific(g_dtj_consumer_key);
288 	jenv = jc->dtjj_jenv;
289 
290 	probe = dtj_new_probedesc(jc, data->dteda_pdesc);
291 	if (!probe) {
292 		return (DTRACE_HANDLE_ABORT);
293 	}
294 	f = dtj_get_fault_name(data->dteda_fault);
295 	if (f) {
296 		fault = (*jenv)->NewStringUTF(jenv, f);
297 		if ((*jenv)->ExceptionCheck(jenv)) {
298 			(*jenv)->DeleteLocalRef(jenv, probe);
299 			return (DTRACE_HANDLE_ABORT);
300 		}
301 	}
302 	switch (data->dteda_fault) {
303 	case DTRACEFLT_BADADDR:
304 	case DTRACEFLT_BADALIGN:
305 	case DTRACEFLT_BADSTACK:
306 		addr = data->dteda_addr;
307 		break;
308 	default:
309 		addr = -1;
310 	}
311 	msg = dtj_NewStringNative(jenv, data->dteda_msg);
312 	if ((*jenv)->ExceptionCheck(jenv)) {
313 		(*jenv)->DeleteLocalRef(jenv, probe);
314 		(*jenv)->DeleteLocalRef(jenv, fault);
315 		return (DTRACE_HANDLE_ABORT);
316 	}
317 	error = (*jenv)->NewObject(jenv, g_error_jc, g_errinit_jm,
318 	    probe,
319 	    data->dteda_edesc->dtepd_epid,
320 	    data->dteda_cpu,
321 	    data->dteda_action,
322 	    data->dteda_offset,
323 	    fault, addr, msg);
324 	(*jenv)->DeleteLocalRef(jenv, msg);
325 	(*jenv)->DeleteLocalRef(jenv, fault);
326 	(*jenv)->DeleteLocalRef(jenv, probe);
327 	if ((*jenv)->ExceptionCheck(jenv)) {
328 		return (DTRACE_HANDLE_ABORT);
329 	}
330 	(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller, g_error_jm, error);
331 	(*jenv)->DeleteLocalRef(jenv, error);
332 	if ((*jenv)->ExceptionCheck(jenv)) {
333 		return (DTRACE_HANDLE_ABORT);
334 	}
335 
336 	return (DTRACE_HANDLE_OK);
337 }
338 
339 /*
340  * Since the function signature does not allow us to return an abort signal, we
341  * need to temporarily clear any pending exception before returning, since
342  * without the abort we can't guarantee that the exception will be checked in
343  * time to prevent invalid JNI function calls.
344  */
345 static void
346 /* ARGSUSED */
347 dtj_prochandler(struct ps_prochandle *P, const char *msg, void *arg)
348 {
349 	dtj_java_consumer_t *jc;
350 	JNIEnv *jenv;
351 
352 	const psinfo_t *prp = Ppsinfo(P);
353 	int pid = Pstatus(P)->pr_pid;
354 	int signal = -1;
355 	char signame[SIG2STR_MAX];
356 	const char *statusname;
357 	int exit = INT_MAX; /* invalid initial status */
358 
359 	jstring status = NULL;
360 	jstring signalName = NULL;
361 	jstring message = NULL;
362 	jobject process = NULL;
363 
364 	jc = pthread_getspecific(g_dtj_consumer_key);
365 	jenv = jc->dtjj_jenv;
366 
367 	switch (Pstate(P)) {
368 	case PS_RUN:
369 		statusname = "RUN";
370 		break;
371 	case PS_STOP:
372 		statusname = "STOP";
373 		break;
374 	case PS_UNDEAD:
375 		statusname = "UNDEAD";
376 		if (prp != NULL) {
377 			exit = WEXITSTATUS(prp->pr_wstat);
378 		}
379 		if (prp != NULL && WIFSIGNALED(prp->pr_wstat)) {
380 			signal = WTERMSIG(prp->pr_wstat);
381 			(void) proc_signame(signal, signame, sizeof (signame));
382 			signalName = (*jenv)->NewStringUTF(jenv, signame);
383 			if ((*jenv)->ExceptionCheck(jenv)) {
384 				goto proc_end;
385 			}
386 		}
387 		++jc->dtjj_consumer->dtjc_procs_ended;
388 		break;
389 	case PS_LOST:
390 		statusname = "LOST";
391 		++jc->dtjj_consumer->dtjc_procs_ended;
392 		break;
393 	case PS_DEAD:
394 		/*
395 		 * PS_DEAD not handled by dtrace.c prochandler, still this is a
396 		 * case of process termination and it can't hurt to handle it.
397 		 */
398 		statusname = "DEAD";
399 		++jc->dtjj_consumer->dtjc_procs_ended;
400 		break;
401 	default:
402 		/*
403 		 * Unexpected, but erring on the side of tolerance by not
404 		 * crashing the consumer.  Failure to notify listeners of
405 		 * process state not handled by the dtrace.c prochandler does
406 		 * not seem serious.
407 		 */
408 		return;
409 	}
410 
411 	status = (*jenv)->NewStringUTF(jenv, statusname);
412 	if ((*jenv)->ExceptionCheck(jenv)) {
413 		(*jenv)->DeleteLocalRef(jenv, signalName);
414 		goto proc_end;
415 	}
416 	if (msg) {
417 		message = dtj_NewStringNative(jenv, msg);
418 		if (!message) {
419 			(*jenv)->DeleteLocalRef(jenv, status);
420 			(*jenv)->DeleteLocalRef(jenv, signalName);
421 			goto proc_end;
422 		}
423 	}
424 	process = (*jenv)->NewObject(jenv, g_process_jc, g_procinit_jm,
425 	    pid, status, signal, signalName, NULL, message);
426 	(*jenv)->DeleteLocalRef(jenv, status);
427 	(*jenv)->DeleteLocalRef(jenv, signalName);
428 	(*jenv)->DeleteLocalRef(jenv, message);
429 	if ((*jenv)->ExceptionCheck(jenv)) {
430 		goto proc_end;
431 	}
432 	if (exit != INT_MAX) {
433 		/* valid exit status */
434 		(*jenv)->CallVoidMethod(jenv, process, g_procexit_jm, exit);
435 		if ((*jenv)->ExceptionCheck(jenv)) {
436 			(*jenv)->DeleteLocalRef(jenv, process);
437 			goto proc_end;
438 		}
439 	}
440 	(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller, g_proc_jm, process);
441 	(*jenv)->DeleteLocalRef(jenv, process);
442 
443 proc_end:
444 
445 	if ((*jenv)->ExceptionCheck(jenv)) {
446 		/*
447 		 * Save the exception so we can rethrow it later when it's safe.
448 		 */
449 		if (!jc->dtjj_exception) {
450 			jthrowable e = (*jenv)->ExceptionOccurred(jenv);
451 			jc->dtjj_exception = e;
452 		}
453 		(*jenv)->ExceptionClear(jenv);
454 	}
455 }
456 
457 static int
458 /* ARGSUSED */
459 dtj_setopthandler(const dtrace_setoptdata_t *data, void *arg)
460 {
461 	dtj_java_consumer_t *jc;
462 
463 	jc = pthread_getspecific(g_dtj_consumer_key);
464 	if (strcmp(data->dtsda_option, "flowindent") == 0) {
465 		jc->dtjj_consumer->dtjc_flow =
466 		    (data->dtsda_newval != DTRACEOPT_UNSET);
467 	}
468 	return (DTRACE_HANDLE_OK);
469 }
470 
471 /*
472  * Most of this function lifted from libdtrace/common/dt_consume.c
473  * dt_print_bytes().
474  */
475 static jobject
476 dtj_bytedata(JNIEnv *jenv, uint32_t nbytes, caddr_t addr)
477 {
478 	/*
479 	 * If the byte stream is a series of printable characters, followed by
480 	 * a terminating byte, we print it out as a string.  Otherwise, we
481 	 * assume that it's something else and just print the bytes.
482 	 */
483 	int i, j;
484 	char *c = addr;
485 
486 	jobject jobj = NULL; /* return value */
487 
488 	if (nbytes == 0) {
489 		return ((*jenv)->NewStringUTF(jenv, ""));
490 	}
491 
492 	for (i = 0; i < nbytes; i++) {
493 		/*
494 		 * We define a "printable character" to be one for which
495 		 * isprint(3C) returns non-zero, isspace(3C) returns non-zero,
496 		 * or a character which is either backspace or the bell.
497 		 * Backspace and the bell are regrettably special because
498 		 * they fail the first two tests -- and yet they are entirely
499 		 * printable.  These are the only two control characters that
500 		 * have meaning for the terminal and for which isprint(3C) and
501 		 * isspace(3C) return 0.
502 		 */
503 		if (isprint(c[i]) || isspace(c[i]) ||
504 		    c[i] == '\b' || c[i] == '\a')
505 			continue;
506 
507 		if (c[i] == '\0' && i > 0) {
508 			/*
509 			 * This looks like it might be a string.  Before we
510 			 * assume that it is indeed a string, check the
511 			 * remainder of the byte range; if it contains
512 			 * additional non-nul characters, we'll assume that
513 			 * it's a binary stream that just happens to look like
514 			 * a string.
515 			 */
516 			for (j = i + 1; j < nbytes; j++) {
517 				if (c[j] != '\0')
518 					break;
519 			}
520 
521 			if (j != nbytes)
522 				break;
523 
524 			/* It's a string */
525 			return (dtj_NewStringNative(jenv, (char *)addr));
526 		}
527 
528 		break;
529 	}
530 
531 	if (i == nbytes) {
532 		/*
533 		 * The byte range is all printable characters, but there is
534 		 * no trailing nul byte.  We'll assume that it's a string.
535 		 */
536 		char *s = malloc(nbytes + 1);
537 		if (!s) {
538 			dtj_throw_out_of_memory(jenv,
539 			    "failed to allocate string value");
540 			return (NULL);
541 		}
542 		(void) strncpy(s, c, nbytes);
543 		s[nbytes] = '\0';
544 		jobj = dtj_NewStringNative(jenv, s);
545 		free(s);
546 		return (jobj);
547 	}
548 
549 	/* return byte array */
550 	jobj = (*jenv)->NewByteArray(jenv, nbytes);
551 	if ((*jenv)->ExceptionCheck(jenv)) {
552 		return (NULL);
553 	}
554 	(*jenv)->SetByteArrayRegion(jenv, (jbyteArray)jobj, 0, nbytes,
555 	    (const jbyte *)c);
556 	if ((*jenv)->ExceptionCheck(jenv)) {
557 		WRAP_EXCEPTION(jenv);
558 		(*jenv)->DeleteLocalRef(jenv, jobj);
559 		return (NULL);
560 	}
561 	return (jobj);
562 }
563 
564 /*
565  * Return NULL if memory could not be allocated (OutOfMemoryError is thrown in
566  * that case).
567  */
568 static jobject
569 dtj_recdata(dtj_java_consumer_t *jc, uint32_t size, caddr_t addr)
570 {
571 	JNIEnv *jenv = jc->dtjj_jenv;
572 	jobject jobj;
573 	jobject jrec;
574 
575 	switch (size) {
576 	case 1:
577 		jobj = (*jenv)->NewObject(jenv, g_int_jc,
578 		    g_intinit_jm, (int)(*((uint8_t *)addr)));
579 		break;
580 	case 2:
581 		jobj = (*jenv)->NewObject(jenv, g_int_jc,
582 		    /* LINTED - alignment */
583 		    g_intinit_jm, (int)(*((uint16_t *)addr)));
584 		break;
585 	case 4:
586 		jobj = (*jenv)->NewObject(jenv, g_int_jc,
587 		    /* LINTED - alignment */
588 		    g_intinit_jm, *((int32_t *)addr));
589 		break;
590 	case 8:
591 		jobj = (*jenv)->NewObject(jenv, g_long_jc,
592 		    /* LINTED - alignment */
593 		    g_longinit_jm, *((int64_t *)addr));
594 		break;
595 	default:
596 		jobj = dtj_bytedata(jenv, size, addr);
597 		break;
598 	}
599 
600 	if (!jobj) {
601 		return (NULL); /* OutOfMemoryError pending */
602 	}
603 
604 	jrec = (*jenv)->NewObject(jenv, g_scalar_jc,
605 	    g_scalarinit_jm, jobj, size);
606 	(*jenv)->DeleteLocalRef(jenv, jobj);
607 
608 	return (jrec);
609 }
610 
611 /*
612  * This is the record handling function passed to dtrace_work().  It differs
613  * from the bufhandler registered with dtrace_handle_buffered() as follows:
614  *
615  * 1.  It does not have access to libdtrace formatted output.
616  * 2.  It is called once for every D program statement, not for every
617  *     output-producing D action or aggregation record.  A statement may be a
618  *     variable assignment, having no size and producing no output.
619  * 3.  It is called for the D exit() action; the bufhandler is not.
620  * 4.  In response to the printa() action, it is called with a record having an
621  *     action of type DTRACEACT_PRINTA.  The bufhandler never sees that action
622  *     value.  It only sees the output-producing aggregation records.
623  * 5.  It is called with a NULL record at the end of each probedata.
624  */
625 static int
626 dtj_chewrec(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec,
627     void *arg)
628 {
629 	dtj_java_consumer_t *jc = arg;
630 	JNIEnv *jenv = jc->dtjj_jenv;
631 
632 	const dtrace_eprobedesc_t *edesc = data->dtpda_edesc;
633 	dtrace_actkind_t act;
634 	int r;
635 
636 	/*
637 	 * Update the record index to that of the current record, or to that of
638 	 * the last record if rec is NULL (signalling end of probe data).
639 	 */
640 	if (rec == NULL) {
641 		r = edesc->dtepd_nrecs; /* end of probe data */
642 	} else {
643 		/*
644 		 * This record handler is called once for the printf() action,
645 		 * but there may be multiple records in the probedata
646 		 * corresponding to the unformatted elements of that printf().
647 		 * We don't know ahead of time how many probedata records
648 		 * libdtrace will consume to produce output for one printf()
649 		 * action, so we look back at the previous call to dtj_chewrec()
650 		 * to see how many probedata records were consumed.  All
651 		 * non-null elements in the range from the previous record index
652 		 * up to and not including the current record index are assumed
653 		 * to be unformatted printf() elements, and will be attached to
654 		 * the PrintfRecord from the previous call.  A null element in
655 		 * that range is the result of a D program statement preceding
656 		 * the printf() that is not a D action.  These generate
657 		 * probedata records accounted for by the null placeholder, but
658 		 * do not advance the probedata offset and are not part of the
659 		 * subsequent printf().
660 		 *
661 		 * If rec->dtrd_size == 0, the record represents a D program
662 		 * statement that is not a D action.  It has no size and does
663 		 * not advance the offset in the probedata.  Handle it normally
664 		 * without special-casing or premature return, since in all
665 		 * cases we look at the previous record later in this function.
666 		 */
667 		for (r = jc->dtjj_consumer->dtjc_probedata_rec_i;
668 		    ((r < edesc->dtepd_nrecs) &&
669 		    (edesc->dtepd_rec[r].dtrd_offset < rec->dtrd_offset));
670 		    ++r) {
671 		}
672 	}
673 
674 	/*
675 	 * Attach the Java representations of the libdtrace data elements
676 	 * pertaining to the previous call to this record handler to the
677 	 * previous Java Record.  (All data elements belonging to the current
678 	 * probedata are added to a single list by the probedata consumer
679 	 * function dtj_chew() before this record consumer function is ever
680 	 * called.) For example, if the previous Record was generated by the
681 	 * printf() action, and dtj_chew() listed 3 records for its 3
682 	 * unformatted elements, those 3 libdtrace records comprise 1
683 	 * PrintfRecord.  Note that we cannot know how many data elements apply
684 	 * to the current rec until we find out the data index where the next
685 	 * rec starts.  (The knowledge of how many probedata records to consume
686 	 * is private to libdtrace.)
687 	 */
688 	if (jc->dtjj_consumer->dtjc_probedata_act == DTRACEACT_PRINTF) {
689 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
690 		    g_pdataattach_jm,
691 		    jc->dtjj_consumer->dtjc_probedata_rec_i, r - 1);
692 		if ((*jenv)->ExceptionCheck(jenv)) {
693 			WRAP_EXCEPTION(jenv);
694 			return (DTRACE_CONSUME_ABORT);
695 		}
696 	}
697 
698 	if (rec == NULL) {
699 		/*
700 		 * End of probe data.  Notify listeners of the new ProbeData
701 		 * instance.
702 		 */
703 		if (jc->dtjj_probedata) {
704 			/* previous probedata */
705 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
706 			    g_pdataclear_jm);
707 			if ((*jenv)->ExceptionCheck(jenv)) {
708 				WRAP_EXCEPTION(jenv);
709 				return (DTRACE_CONSUME_ABORT);
710 			}
711 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller,
712 			    g_pdatanext_jm, jc->dtjj_probedata);
713 			(*jenv)->DeleteLocalRef(jenv, jc->dtjj_probedata);
714 			jc->dtjj_probedata = NULL;
715 			if ((*jenv)->ExceptionCheck(jenv)) {
716 				/*
717 				 * Do not wrap exception thrown from
718 				 * ConsumerListener.
719 				 */
720 				return (DTRACE_CONSUME_ABORT);
721 			}
722 		}
723 		(*jenv)->DeleteLocalRef(jenv, jc->dtjj_printa_buffer);
724 		jc->dtjj_printa_buffer = NULL;
725 		return (DTRACE_CONSUME_NEXT);
726 	}
727 
728 	act = rec->dtrd_action;
729 
730 	/* Set previous record action and data index to current */
731 	jc->dtjj_consumer->dtjc_probedata_act = act;
732 	jc->dtjj_consumer->dtjc_probedata_rec_i = r;
733 
734 	switch (act) {
735 	case DTRACEACT_DIFEXPR:
736 		if (rec->dtrd_size == 0) {
737 			/*
738 			 * The current record is not a D action, but a program
739 			 * statement such as a variable assignment, not to be
740 			 * confused with the trace() action.
741 			 */
742 			break;
743 		}
744 		/*
745 		 * Add a Record for the trace() action that references the
746 		 * native probedata element listed at the current index.
747 		 */
748 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
749 		    g_pdataadd_trace_jm,
750 		    jc->dtjj_consumer->dtjc_probedata_rec_i);
751 		if ((*jenv)->ExceptionCheck(jenv)) {
752 			WRAP_EXCEPTION(jenv);
753 			return (DTRACE_CONSUME_ABORT);
754 		}
755 		break;
756 	case DTRACEACT_PRINTF:
757 		/*
758 		 * Just add an empty PrintfRecord for now.  We'll attach the
759 		 * unformatted elements in a subsequent call to this function.
760 		 * (We don't know how many there will be.)
761 		 */
762 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
763 		    g_pdataadd_printf_jm);
764 		if ((*jenv)->ExceptionCheck(jenv)) {
765 			WRAP_EXCEPTION(jenv);
766 			return (DTRACE_CONSUME_ABORT);
767 		}
768 		/* defer formatted string to dtj_bufhandler() */
769 		break;
770 	case DTRACEACT_PRINTA: {
771 		jobject jbuf = NULL;
772 
773 		dtj_aggwalk_init(jc);
774 		if ((*jenv)->ExceptionCheck(jenv)) {
775 			WRAP_EXCEPTION(jenv);
776 			return (DTRACE_CONSUME_ABORT);
777 		}
778 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
779 		    g_pdataadd_printa_jm,
780 		    jc->dtjj_consumer->dtjc_printa_snaptime,
781 		    (rec->dtrd_format != 0));
782 		if ((*jenv)->ExceptionCheck(jenv)) {
783 			WRAP_EXCEPTION(jenv);
784 			return (DTRACE_CONSUME_ABORT);
785 		}
786 		if (jc->dtjj_printa_buffer == NULL) {
787 			/*
788 			 * Create a StringBuilder to collect the pieces of
789 			 * formatted output into a single String.
790 			 */
791 			jbuf = (*jenv)->NewObject(jenv, g_buf_jc,
792 			    g_bufinit_jm);
793 			if (!jbuf) {
794 				/* OutOfMemoryError pending */
795 				return (DTRACE_CONSUME_ABORT);
796 			}
797 			jc->dtjj_printa_buffer = jbuf;
798 		}
799 		/* defer aggregation records to dtj_bufhandler() */
800 		break;
801 	}
802 	case DTRACEACT_EXIT:
803 		/*
804 		 * Add a Record for the exit() action that references the native
805 		 * probedata element listed at the current index.
806 		 */
807 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
808 		    g_pdataadd_exit_jm,
809 		    jc->dtjj_consumer->dtjc_probedata_rec_i);
810 		if ((*jenv)->ExceptionCheck(jenv)) {
811 			WRAP_EXCEPTION(jenv);
812 			return (DTRACE_CONSUME_ABORT);
813 		}
814 		return (DTRACE_CONSUME_NEXT);
815 	}
816 
817 	return (DTRACE_CONSUME_THIS);
818 }
819 
820 /*
821  * This is the probe handling function passed to dtrace_work().  It is is called
822  * once every time a probe fires.  It is the first of all the callbacks for the
823  * current probe.  It is followed by multiple callbacks to dtj_chewrec(), one
824  * for each probedata record.  Each call to dtj_chewrec() is followed by zero or
825  * more callbacks to the bufhandler, one for each output-producing action or
826  * aggregation record.
827  */
828 static int
829 dtj_chew(const dtrace_probedata_t *data, void *arg)
830 {
831 	dtj_java_consumer_t *jc = arg;
832 	JNIEnv *jenv = jc->dtjj_jenv;
833 
834 	dtrace_eprobedesc_t *edesc;
835 	dtrace_probedesc_t *pdesc;
836 	dtrace_recdesc_t *rec;
837 	int epid;
838 	int cpu;
839 	int nrecs;
840 	int i;
841 
842 	jobject jpdata = NULL;
843 	jobject jprobe = NULL;
844 	jobject jflow = NULL;
845 	jstring jflowkind = NULL;
846 	jobject jobj = NULL;
847 
848 	edesc = data->dtpda_edesc;
849 	epid = (int)edesc->dtepd_epid;
850 	pdesc = data->dtpda_pdesc;
851 	cpu = (int)data->dtpda_cpu;
852 	if ((jprobe = dtj_new_probedesc(jc, pdesc)) == NULL) {
853 		/* java exception pending */
854 		return (DTRACE_CONSUME_ABORT);
855 	}
856 	nrecs = edesc->dtepd_nrecs;
857 
858 	if (jc->dtjj_consumer->dtjc_flow) {
859 		const char *kind;
860 		switch (data->dtpda_flow) {
861 		case DTRACEFLOW_ENTRY:
862 			kind = "ENTRY";
863 			break;
864 		case DTRACEFLOW_RETURN:
865 			kind = "RETURN";
866 			break;
867 		case DTRACEFLOW_NONE:
868 			kind = "NONE";
869 			break;
870 		default:
871 			kind = NULL;
872 		}
873 		if (kind != NULL) {
874 			int depth;
875 			jflowkind = (*jenv)->NewStringUTF(jenv, kind);
876 			if ((*jenv)->ExceptionCheck(jenv)) {
877 				WRAP_EXCEPTION(jenv);
878 				(*jenv)->DeleteLocalRef(jenv, jprobe);
879 				return (DTRACE_CONSUME_ABORT);
880 			}
881 			/*
882 			 * Use the knowledge that libdtrace indents 2 spaces per
883 			 * level in the call stack to calculate the depth.
884 			 */
885 			depth = (data->dtpda_indent / 2);
886 			jflow = (*jenv)->NewObject(jenv, g_flow_jc,
887 			    g_flowinit_jm, jflowkind, depth);
888 			(*jenv)->DeleteLocalRef(jenv, jflowkind);
889 			if ((*jenv)->ExceptionCheck(jenv)) {
890 				WRAP_EXCEPTION(jenv);
891 				(*jenv)->DeleteLocalRef(jenv, jprobe);
892 				return (DTRACE_CONSUME_ABORT);
893 			}
894 		}
895 	}
896 
897 	/* Create ProbeData instance */
898 	jpdata = (*jenv)->NewObject(jenv, g_pdata_jc, g_pdatainit_jm,
899 	    epid, cpu, jprobe, jflow, nrecs);
900 	(*jenv)->DeleteLocalRef(jenv, jprobe);
901 	(*jenv)->DeleteLocalRef(jenv, jflow);
902 	if ((*jenv)->ExceptionCheck(jenv)) {
903 		WRAP_EXCEPTION(jenv);
904 		return (DTRACE_CONSUME_ABORT);
905 	}
906 
907 	/*
908 	 * Populate the ProbeData list of Java data elements in advance so we
909 	 * don't need to peek back in the record handler at libdtrace records
910 	 * that have already been consumed.  In the Java API, each ProbeData
911 	 * Record is generated by one D action, while in the native libdtrace
912 	 * there may be more than one probedata record (each a single data
913 	 * element) per D action.  For example PrintfRecord has multiple
914 	 * unformatted elements, each represented by a native probedata record,
915 	 * but combined by the API into a single PrintfRecord.
916 	 */
917 	for (i = 0; i < nrecs; ++i) {
918 		rec = &edesc->dtepd_rec[i];
919 		/*
920 		 * A statement that is not a D action, such as assignment to a
921 		 * variable, has no size.  Add a NULL placeholder to the scratch
922 		 * list of Java probedata elements in that case.
923 		 */
924 		jobj = NULL; /* initialize object reference to null */
925 		if (rec->dtrd_size > 0) {
926 			if (dtj_is_stack_action(rec->dtrd_action)) {
927 				jobj = dtj_new_probedata_stack_record(data,
928 				    rec, jc);
929 			} else if (dtj_is_symbol_action(rec->dtrd_action)) {
930 				jobj = dtj_new_probedata_symbol_record(data,
931 				    rec, jc);
932 			} else {
933 				jobj = dtj_recdata(jc, rec->dtrd_size,
934 				    (data->dtpda_data + rec->dtrd_offset));
935 			}
936 			if ((*jenv)->ExceptionCheck(jenv)) {
937 				WRAP_EXCEPTION(jenv);
938 				(*jenv)->DeleteLocalRef(jenv, jpdata);
939 				return (DTRACE_CONSUME_ABORT);
940 			}
941 		}
942 
943 		(*jenv)->CallVoidMethod(jenv, jpdata, g_pdataadd_jm, jobj);
944 		(*jenv)->DeleteLocalRef(jenv, jobj);
945 		if ((*jenv)->ExceptionCheck(jenv)) {
946 			WRAP_EXCEPTION(jenv);
947 			(*jenv)->DeleteLocalRef(jenv, jpdata);
948 			return (DTRACE_CONSUME_ABORT);
949 		}
950 	}
951 
952 	if (jc->dtjj_probedata != NULL) {
953 		dtj_throw_illegal_state(jenv, "unfinished probedata");
954 		WRAP_EXCEPTION(jenv);
955 		(*jenv)->DeleteLocalRef(jenv, jpdata);
956 		return (DTRACE_CONSUME_ABORT);
957 	}
958 	jc->dtjj_probedata = jpdata;
959 
960 	/* Initialize per-consumer probedata fields */
961 	jc->dtjj_consumer->dtjc_probedata_rec_i = 0;
962 	jc->dtjj_consumer->dtjc_probedata_act = DTRACEACT_NONE;
963 	dtj_aggwalk_init(jc);
964 	if ((*jenv)->ExceptionCheck(jenv)) {
965 		WRAP_EXCEPTION(jenv);
966 		return (DTRACE_CONSUME_ABORT);
967 	}
968 
969 	return (DTRACE_CONSUME_THIS);
970 }
971 
972 /*
973  * This is the buffered output handler registered with dtrace_handle_buffered().
974  * It's purpose is to make the output of the libdtrace print routines available
975  * to this API, without writing any of it to a file (such as stdout).  This is
976  * needed for the stack(), ustack(), and jstack() actions to get human-readable
977  * stack values, since there is no public function in libdtrace to convert stack
978  * values to strings.  It is also used to get the formatted output of the D
979  * printf() and printa() actions.
980  *
981  * The bufhandler is called once for each output-producing, non-aggregating D
982  * action, such as trace() or printf(), and once for each libdtrace aggregation
983  * record (whether in response to the D printa() action, or the Consumer
984  * getAggregate() method).  In the simple printa() case that takes one
985  * aggregation and does not specify a format string, there is one libdtrace
986  * record per tuple element plus one for the corresponding value.  The complete
987  * tuple/value pair becomes a single AggregationRecord exported by the API.
988  * When multiple aggregations are passed to printa(), each tuple is associated
989  * with a list of values, one from each aggregation.  If a printa() format
990  * string does not specify placeholders for every aggregation value and tuple
991  * member, callbacks for those values and tuple members are omitted (and the
992  * data is omitted from the resulting PrintaRecord).
993  *
994  * Notes to characterize some non-obvious bufhandler behavior:
995  *
996  * 1. dtj_bufhandler() is never called with bufdata->dtbda_recdesc->dtrd_action
997  * DTRACEACT_PRINTA.  That action only appears in the probedata consumer
998  * functions dtj_chew() and dtj_chewrec() before the bufhandler is called with
999  * subsequent aggregation records.
1000  *
1001  * 2. If printa() specifies a format string argument, then the bufhandler is
1002  * called only for those elements of the tuple/value pair that are included in
1003  * the format string.  If a stack() tuple member is omitted from the format
1004  * string, its human-readable representation will not be available to this API,
1005  * so the stack frame array is also omitted from the resulting
1006  * AggregationRecord.  The bufhandler is also called once for each string of
1007  * characters surrounding printa() format string placeholders.  For example,
1008  * "  %@d %d stack%k\n" results in the following callbacks:
1009  *  - two spaces
1010  *  - the aggregation value
1011  *  - a single space
1012  *  - the first tuple member (an integer)
1013  *  - " stack"
1014  *  - the second tuple member (a stack)
1015  *  - a newline
1016  * A NULL record (NULL dtbda_recdesc) distinguishes a callback with interstitial
1017  * format string characters from a callback with a tuple member or aggregation
1018  * value (which has a non-NULL recdesc).  The contents are also distinguished by
1019  * the following flags:
1020  *  DTRACE_BUFDATA_AGGKEY
1021  *  DTRACE_BUFDATA_AGGVAL
1022  *  DTRACE_BUFDATA_AGGFORMAT
1023  *  DTRACE_BUFDATA_AGGLAST
1024  *
1025  * There is no final callback with the complete formatted string, so that must
1026  * be concatenated across multiple callbacks to the bufhandler.
1027  *
1028  * 3. bufdata->dtbda_probe->dtpda_data may be overwritten by libdtrace print
1029  * routines.  The address is cached in the dtj_chew() function in case it is
1030  * needed in the bufhandler.
1031  */
1032 static int
1033 /* ARGSUSED */
1034 dtj_bufhandler(const dtrace_bufdata_t *bufdata, void *arg)
1035 {
1036 	dtj_java_consumer_t *jc;
1037 	JNIEnv *jenv;
1038 	const dtrace_recdesc_t *rec;
1039 	dtrace_actkind_t act = DTRACEACT_NONE;
1040 	const char *s;
1041 
1042 	jobject jstr = NULL;
1043 
1044 	/*
1045 	 * Get the thread-specific java consumer.  The bufhandler needs access
1046 	 * to the correct JNI state specific to either the consumer loop or the
1047 	 * getAggregate() call (aggregation snapshots can be requested
1048 	 * asynchronously while the consumer loop generates PrintaRecords in
1049 	 * dtrace_work() for ConsumerListeners).
1050 	 */
1051 	jc = pthread_getspecific(g_dtj_consumer_key);
1052 	jenv = jc->dtjj_jenv;
1053 
1054 	/*
1055 	 * In at least one corner case (printa with multiple aggregations and a
1056 	 * format string that does not completely specify the tuple), returning
1057 	 * DTRACE_HANDLE_ABORT does not prevent a subsequent callback to this
1058 	 * bufhandler.  This check ensures that the invalid call is ignored.
1059 	 */
1060 	if ((*jenv)->ExceptionCheck(jenv)) {
1061 		return (DTRACE_HANDLE_ABORT);
1062 	}
1063 
1064 	if (bufdata->dtbda_aggdata) {
1065 		return (dtj_agghandler(bufdata, jc));
1066 	}
1067 
1068 	s = bufdata->dtbda_buffered;
1069 	if (s == NULL) {
1070 		return (DTRACE_HANDLE_OK);
1071 	}
1072 
1073 	rec = bufdata->dtbda_recdesc;
1074 	if (rec) {
1075 		act = rec->dtrd_action;
1076 	}
1077 
1078 	switch (act) {
1079 	case DTRACEACT_DIFEXPR:
1080 		/* trace() action */
1081 		break;
1082 	case DTRACEACT_PRINTF:
1083 		/*
1084 		 * Only the formatted string was not available to dtj_chewrec(),
1085 		 * so we attach that now.
1086 		 */
1087 		jstr = dtj_NewStringNative(jenv, s);
1088 		if ((*jenv)->ExceptionCheck(jenv)) {
1089 			WRAP_EXCEPTION(jenv);
1090 			return (DTRACE_HANDLE_ABORT);
1091 		}
1092 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1093 		    g_pdataset_formatted_jm, jstr);
1094 		(*jenv)->DeleteLocalRef(jenv, jstr);
1095 		if ((*jenv)->ExceptionCheck(jenv)) {
1096 			WRAP_EXCEPTION(jenv);
1097 			return (DTRACE_HANDLE_ABORT);
1098 		}
1099 		break;
1100 	case DTRACEACT_STACK:
1101 	case DTRACEACT_USTACK:
1102 	case DTRACEACT_JSTACK:
1103 		/* stand-alone stack(), ustack(), or jstack() action */
1104 		jstr = (*jenv)->NewStringUTF(jenv, s);
1105 		if (!jstr) {
1106 			/* OutOfMemoryError pending */
1107 			return (DTRACE_HANDLE_ABORT);
1108 		}
1109 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1110 		    g_pdataadd_stack_jm,
1111 		    jc->dtjj_consumer->dtjc_probedata_rec_i, jstr);
1112 		(*jenv)->DeleteLocalRef(jenv, jstr);
1113 		if ((*jenv)->ExceptionCheck(jenv)) {
1114 			WRAP_EXCEPTION(jenv);
1115 			return (DTRACE_HANDLE_ABORT);
1116 		}
1117 		break;
1118 	case DTRACEACT_USYM:
1119 	case DTRACEACT_UADDR:
1120 	case DTRACEACT_UMOD:
1121 	case DTRACEACT_SYM:
1122 	case DTRACEACT_MOD:
1123 		/* stand-alone symbol lookup action */
1124 		jstr = (*jenv)->NewStringUTF(jenv, s);
1125 		if (!jstr) {
1126 			/* OutOfMemoryError pending */
1127 			return (DTRACE_HANDLE_ABORT);
1128 		}
1129 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1130 		    g_pdataadd_symbol_jm,
1131 		    jc->dtjj_consumer->dtjc_probedata_rec_i, jstr);
1132 		(*jenv)->DeleteLocalRef(jenv, jstr);
1133 		if ((*jenv)->ExceptionCheck(jenv)) {
1134 			WRAP_EXCEPTION(jenv);
1135 			return (DTRACE_HANDLE_ABORT);
1136 		}
1137 		break;
1138 	default:
1139 		/*
1140 		 * The record handler dtj_chewrec() defers nothing else to this
1141 		 * bufhandler.
1142 		 */
1143 		break;
1144 	}
1145 
1146 	return (DTRACE_HANDLE_OK);
1147 }
1148 
1149 static boolean_t
1150 dtj_is_stack_action(dtrace_actkind_t act)
1151 {
1152 	boolean_t stack_action;
1153 	switch (act) {
1154 	case DTRACEACT_STACK:
1155 	case DTRACEACT_USTACK:
1156 	case DTRACEACT_JSTACK:
1157 		stack_action = B_TRUE;
1158 		break;
1159 	default:
1160 		stack_action = B_FALSE;
1161 	}
1162 	return (stack_action);
1163 }
1164 
1165 static boolean_t
1166 dtj_is_symbol_action(dtrace_actkind_t act)
1167 {
1168 	boolean_t symbol_action;
1169 	switch (act) {
1170 	case DTRACEACT_USYM:
1171 	case DTRACEACT_UADDR:
1172 	case DTRACEACT_UMOD:
1173 	case DTRACEACT_SYM:
1174 	case DTRACEACT_MOD:
1175 		symbol_action = B_TRUE;
1176 		break;
1177 	default:
1178 		symbol_action = B_FALSE;
1179 	}
1180 	return (symbol_action);
1181 }
1182 
1183 /*
1184  * Called by get_aggregate() to clear only those aggregations specified by the
1185  * caller.
1186  */
1187 static int
1188 dtj_clear(const dtrace_aggdata_t *data, void *arg)
1189 {
1190 	dtj_java_consumer_t *jc = arg;
1191 	jboolean cleared = JNI_FALSE;
1192 
1193 	jstring jname = NULL;
1194 
1195 	if (jc->dtjj_aggregate_spec) {
1196 		JNIEnv *jenv = jc->dtjj_jenv;
1197 
1198 		dtrace_aggdesc_t *aggdesc = data->dtada_desc;
1199 
1200 		jname = (*jenv)->NewStringUTF(jenv, aggdesc->dtagd_name);
1201 		if (!jname) {
1202 			/* java exception pending */
1203 			return (DTRACE_AGGWALK_ABORT);
1204 		}
1205 
1206 		cleared = (*jenv)->CallBooleanMethod(jenv,
1207 		    jc->dtjj_aggregate_spec, g_aggspec_cleared_jm, jname);
1208 		(*jenv)->DeleteLocalRef(jenv, jname);
1209 		if ((*jenv)->ExceptionCheck(jenv)) {
1210 			WRAP_EXCEPTION(jenv);
1211 			return (DTRACE_AGGWALK_ABORT);
1212 		}
1213 	}
1214 
1215 	return (cleared ? DTRACE_AGGWALK_CLEAR : DTRACE_AGGWALK_NEXT);
1216 }
1217 
1218 static int64_t
1219 dtj_average(caddr_t addr, uint64_t normal)
1220 {
1221 	/* LINTED - alignment */
1222 	int64_t *data = (int64_t *)addr;
1223 
1224 	return (data[0] ?
1225 	    (data[1] / (int64_t)normal / data[0]) : 0);
1226 }
1227 
1228 static int64_t
1229 dtj_avg_total(caddr_t addr, uint64_t normal)
1230 {
1231 	/* LINTED - alignment */
1232 	int64_t *data = (int64_t *)addr;
1233 
1234 	return (data[1] / (int64_t)normal);
1235 }
1236 
1237 static int64_t
1238 dtj_avg_count(caddr_t addr)
1239 {
1240 	/* LINTED - alignment */
1241 	int64_t *data = (int64_t *)addr;
1242 
1243 	return (data[0]);
1244 }
1245 
1246 static jobject
1247 dtj_stddev_total_squares(JNIEnv *jenv, caddr_t addr, uint64_t normal)
1248 {
1249 	jobject val128;
1250 
1251 	/* LINTED - alignment */
1252 	uint64_t *data = (uint64_t *)addr;
1253 
1254 	if (data[0] == 0) {
1255 		val128 = (*jenv)->CallStaticObjectMethod(jenv, g_bigint_jc,
1256 		    g_bigint_val_jsm, (uint64_t)0);
1257 	} else {
1258 		val128 = dtj_int128(jenv, data[3], data[2]);
1259 
1260 		if (normal != 1) {
1261 			jobject divisor;
1262 			jobject tmp;
1263 
1264 			divisor = (*jenv)->CallStaticObjectMethod(jenv,
1265 			    g_bigint_jc, g_bigint_val_jsm, normal);
1266 			tmp = val128;
1267 			val128 = (*jenv)->CallObjectMethod(jenv, tmp,
1268 			    g_bigint_div_jm, divisor);
1269 			(*jenv)->DeleteLocalRef(jenv, tmp);
1270 			(*jenv)->DeleteLocalRef(jenv, divisor);
1271 		}
1272 	}
1273 
1274 	return (val128);
1275 }
1276 
1277 /*
1278  * Return NULL if a java exception is pending, otherwise return a new
1279  * StddevValue instance.
1280  */
1281 static jobject
1282 dtj_stddev(JNIEnv *jenv, caddr_t addr, uint64_t normal)
1283 {
1284 	jobject total_squares;
1285 	jobject stddev;
1286 
1287 	total_squares = dtj_stddev_total_squares(jenv, addr, normal);
1288 	stddev = (*jenv)->NewObject(jenv, g_aggstddev_jc, g_aggstddevinit_jm,
1289 	    dtj_avg_count(addr), dtj_avg_total(addr, normal), total_squares);
1290 	(*jenv)->DeleteLocalRef(jenv, total_squares);
1291 
1292 	return (stddev);
1293 }
1294 
1295 static jobject
1296 dtj_new_probedata_stack_record(const dtrace_probedata_t *data,
1297     const dtrace_recdesc_t *rec, dtj_java_consumer_t *jc)
1298 {
1299 	caddr_t addr;
1300 
1301 	/* Get raw stack data */
1302 	addr = data->dtpda_data + rec->dtrd_offset;
1303 	return (dtj_new_stack_record(addr, rec, jc));
1304 }
1305 
1306 static jobject
1307 dtj_new_tuple_stack_record(const dtrace_aggdata_t *data,
1308     const dtrace_recdesc_t *rec, const char *s, dtj_java_consumer_t *jc)
1309 {
1310 	caddr_t addr;
1311 	JNIEnv *jenv = jc->dtjj_jenv;
1312 
1313 	jobjectArray frames = NULL;
1314 	jobject jobj = NULL; /* tuple element */
1315 	jstring jstr = NULL;
1316 
1317 	/* Get raw stack data */
1318 	addr = data->dtada_data + rec->dtrd_offset;
1319 	jobj = dtj_new_stack_record(addr, rec, jc);
1320 	if (!jobj) {
1321 		return (NULL); /* java exception pending */
1322 	}
1323 
1324 	jstr = dtj_NewStringNative(jenv, s);
1325 	if ((*jenv)->ExceptionCheck(jenv)) {
1326 		(*jenv)->DeleteLocalRef(jenv, jobj);
1327 		return (NULL);
1328 	}
1329 	frames = (*jenv)->CallStaticObjectMethod(jenv, g_stack_jc,
1330 	    g_parsestack_jsm, jstr);
1331 	(*jenv)->DeleteLocalRef(jenv, jstr);
1332 	if ((*jenv)->ExceptionCheck(jenv)) {
1333 		(*jenv)->DeleteLocalRef(jenv, jobj);
1334 		return (NULL);
1335 	}
1336 	dtj_attach_frames(jc, jobj, frames);
1337 	(*jenv)->DeleteLocalRef(jenv, frames);
1338 	if ((*jenv)->ExceptionCheck(jenv)) {
1339 		WRAP_EXCEPTION(jenv);
1340 		return (NULL);
1341 	}
1342 
1343 	return (jobj);
1344 }
1345 
1346 static jobject
1347 dtj_new_probedata_symbol_record(const dtrace_probedata_t *data,
1348     const dtrace_recdesc_t *rec, dtj_java_consumer_t *jc)
1349 {
1350 	caddr_t addr;
1351 
1352 	addr = data->dtpda_data + rec->dtrd_offset;
1353 	return (dtj_new_symbol_record(addr, rec, jc));
1354 }
1355 
1356 static jobject
1357 dtj_new_tuple_symbol_record(const dtrace_aggdata_t *data,
1358     const dtrace_recdesc_t *rec, const char *s, dtj_java_consumer_t *jc)
1359 {
1360 	caddr_t addr;
1361 	JNIEnv *jenv = jc->dtjj_jenv;
1362 
1363 	jobject jobj = NULL; /* tuple element */
1364 	jstring jstr = NULL; /* lookup value */
1365 	jstring tstr = NULL; /* trimmed lookup value */
1366 
1367 	addr = data->dtada_data + rec->dtrd_offset;
1368 	jobj = dtj_new_symbol_record(addr, rec, jc);
1369 	if (!jobj) {
1370 		return (NULL); /* java exception pending */
1371 	}
1372 
1373 	/* Get symbol lookup */
1374 	jstr = (*jenv)->NewStringUTF(jenv, s);
1375 	if (!jstr) {
1376 		/* OutOfMemoryError pending */
1377 		(*jenv)->DeleteLocalRef(jenv, jobj);
1378 		return (NULL);
1379 	}
1380 	/* Trim leading and trailing whitespace */
1381 	tstr = (*jenv)->CallObjectMethod(jenv, jstr, g_trim_jm);
1382 	/* trim() returns a new string; don't leak the old one */
1383 	(*jenv)->DeleteLocalRef(jenv, jstr);
1384 	jstr = tstr;
1385 	tstr = NULL;
1386 
1387 	dtj_attach_name(jc, jobj, jstr);
1388 	(*jenv)->DeleteLocalRef(jenv, jstr);
1389 	if ((*jenv)->ExceptionCheck(jenv)) {
1390 		WRAP_EXCEPTION(jenv);
1391 		return (NULL);
1392 	}
1393 
1394 	return (jobj);
1395 }
1396 
1397 /* Caller must be holding per-consumer lock */
1398 static void
1399 dtj_aggwalk_init(dtj_java_consumer_t *jc)
1400 {
1401 	jc->dtjj_consumer->dtjc_aggid = -1;
1402 	jc->dtjj_consumer->dtjc_expected = -1;
1403 	if (jc->dtjj_tuple != NULL) {
1404 		/* assert without crashing */
1405 		dtj_throw_illegal_state(jc->dtjj_jenv,
1406 		    "stale aggregation tuple");
1407 	}
1408 }
1409 
1410 static jobject
1411 dtj_new_stack_record(const caddr_t addr, const dtrace_recdesc_t *rec,
1412     dtj_java_consumer_t *jc)
1413 {
1414 	JNIEnv *jenv = jc->dtjj_jenv;
1415 
1416 	dtrace_actkind_t act;
1417 	uint64_t *pc;
1418 	pid_t pid = -1;
1419 	int size; /* size of raw bytes not including trailing zeros */
1420 	int i; /* index of last non-zero byte */
1421 
1422 	jbyteArray raw = NULL;
1423 	jobject stack = NULL; /* return value */
1424 
1425 	/* trim trailing zeros */
1426 	for (i = rec->dtrd_size - 1; (i >= 0) && !addr[i]; --i) {
1427 	}
1428 	size = (i + 1);
1429 	raw = (*jenv)->NewByteArray(jenv, size);
1430 	if (!raw) {
1431 		return (NULL); /* OutOfMemoryError pending */
1432 	}
1433 	(*jenv)->SetByteArrayRegion(jenv, raw, 0, size,
1434 	    (const jbyte *)addr);
1435 	if ((*jenv)->ExceptionCheck(jenv)) {
1436 		WRAP_EXCEPTION(jenv);
1437 		(*jenv)->DeleteLocalRef(jenv, raw);
1438 		return (NULL);
1439 	}
1440 
1441 	/* Create StackValueRecord instance from raw stack data */
1442 	act = rec->dtrd_action;
1443 	switch (act) {
1444 	case DTRACEACT_STACK:
1445 		stack = (*jenv)->NewObject(jenv, g_stack_jc,
1446 		    g_stackinit_jm, raw);
1447 		break;
1448 	case DTRACEACT_USTACK:
1449 	case DTRACEACT_JSTACK:
1450 		/* Get pid of user process */
1451 		pc = (uint64_t *)(uintptr_t)addr;
1452 		pid = (pid_t)*pc;
1453 		stack = (*jenv)->NewObject(jenv, g_ustack_jc,
1454 		    g_ustackinit_jm, pid, raw);
1455 		break;
1456 	default:
1457 		dtj_throw_illegal_argument(jenv,
1458 		    "Expected stack action, got %d\n", act);
1459 	}
1460 	(*jenv)->DeleteLocalRef(jenv, raw);
1461 	if ((*jenv)->ExceptionCheck(jenv)) {
1462 		WRAP_EXCEPTION(jenv);
1463 		return (NULL);
1464 	}
1465 	return (stack);
1466 }
1467 
1468 static jobject
1469 dtj_new_symbol_record(const caddr_t addr, const dtrace_recdesc_t *rec,
1470     dtj_java_consumer_t *jc)
1471 {
1472 	JNIEnv *jenv = jc->dtjj_jenv;
1473 
1474 	dtrace_actkind_t act;
1475 	uint64_t *pc;
1476 	pid_t pid = -1;
1477 
1478 	jobject symbol = NULL; /* return value */
1479 
1480 	act = rec->dtrd_action;
1481 	switch (act) {
1482 	case DTRACEACT_SYM:
1483 	case DTRACEACT_MOD:
1484 		/* LINTED - alignment */
1485 		pc = (uint64_t *)addr;
1486 		symbol = (*jenv)->NewObject(jenv, g_symbol_jc,
1487 		    g_symbolinit_jm, *pc);
1488 		break;
1489 	case DTRACEACT_USYM:
1490 	case DTRACEACT_UADDR:
1491 	case DTRACEACT_UMOD:
1492 		/* Get pid of user process */
1493 		pc = (uint64_t *)(uintptr_t)addr;
1494 		pid = (pid_t)*pc;
1495 		++pc;
1496 		symbol = (*jenv)->NewObject(jenv, g_usymbol_jc,
1497 		    g_usymbolinit_jm, pid, *pc);
1498 		break;
1499 	default:
1500 		dtj_throw_illegal_argument(jenv,
1501 		    "Expected stack action, got %d\n", act);
1502 	}
1503 	if ((*jenv)->ExceptionCheck(jenv)) {
1504 		WRAP_EXCEPTION(jenv);
1505 		return (NULL);
1506 	}
1507 	return (symbol);
1508 }
1509 
1510 /*
1511  * Return NULL if java exception pending, otherwise return Distribution value.
1512  */
1513 static jobject
1514 dtj_new_distribution(const dtrace_aggdata_t *data, const dtrace_recdesc_t *rec,
1515     dtj_java_consumer_t *jc)
1516 {
1517 	JNIEnv *jenv = jc->dtjj_jenv;
1518 
1519 	jlongArray jbuckets = NULL;
1520 	jobject jdist = NULL; /* return value */
1521 
1522 	dtrace_actkind_t act = rec->dtrd_action;
1523 	/* LINTED - alignment */
1524 	int64_t *aggbuckets = (int64_t *)
1525 	    (data->dtada_data + rec->dtrd_offset);
1526 	size_t size = rec->dtrd_size;
1527 	int64_t value;
1528 	uint64_t normal = data->dtada_normal;
1529 	int64_t base, step;
1530 	int levels;
1531 	int n; /* number of buckets */
1532 
1533 	/* distribution */
1534 	if (act == DTRACEAGG_LQUANTIZE) {
1535 		/* first "bucket" used for range and step */
1536 		value = *aggbuckets++;
1537 		base = DTRACE_LQUANTIZE_BASE(value);
1538 		step = DTRACE_LQUANTIZE_STEP(value);
1539 		levels = DTRACE_LQUANTIZE_LEVELS(value);
1540 		size -= sizeof (int64_t); /* exclude non-bucket */
1541 		/*
1542 		 * Add one for the base bucket and one for the bucket of values
1543 		 * less than the base.
1544 		 */
1545 		n = levels + 2;
1546 	} else {
1547 		n = DTRACE_QUANTIZE_NBUCKETS;
1548 		levels = n - 1; /* levels excludes base */
1549 	}
1550 	if (size != (n * sizeof (uint64_t)) || n < 1) {
1551 		dtj_throw_illegal_state(jenv,
1552 		    "size mismatch: record %d, buckets %d", size,
1553 		    (n * sizeof (uint64_t)));
1554 		WRAP_EXCEPTION(jenv);
1555 		return (NULL);
1556 	}
1557 
1558 	jbuckets = (*jenv)->NewLongArray(jenv, n);
1559 	if (!jbuckets) {
1560 		return (NULL); /* exception pending */
1561 	}
1562 	if (n > 0) {
1563 		(*jenv)->SetLongArrayRegion(jenv, jbuckets, 0, n, aggbuckets);
1564 		/* check for ArrayIndexOutOfBounds */
1565 		if ((*jenv)->ExceptionCheck(jenv)) {
1566 			WRAP_EXCEPTION(jenv);
1567 			(*jenv)->DeleteLocalRef(jenv, jbuckets);
1568 			return (NULL);
1569 		}
1570 	}
1571 
1572 	if (act == DTRACEAGG_LQUANTIZE) {
1573 		/* Must pass 64-bit base and step or constructor gets junk. */
1574 		jdist = (*jenv)->NewObject(jenv, g_ldist_jc, g_ldistinit_jm,
1575 		    base, step, jbuckets);
1576 	} else {
1577 		jdist = (*jenv)->NewObject(jenv, g_dist_jc, g_distinit_jm,
1578 		    jbuckets);
1579 	}
1580 
1581 	(*jenv)->DeleteLocalRef(jenv, jbuckets);
1582 	if (!jdist) {
1583 		return (NULL); /* exception pending */
1584 	}
1585 
1586 	if (normal != 1) {
1587 		(*jenv)->CallVoidMethod(jenv, jdist, g_dist_normal_jm, normal);
1588 		if ((*jenv)->ExceptionCheck(jenv)) {
1589 			WRAP_EXCEPTION(jenv);
1590 			(*jenv)->DeleteLocalRef(jenv, jdist);
1591 			return (NULL);
1592 		}
1593 	}
1594 	return (jdist);
1595 }
1596 
1597 static void
1598 dtj_attach_frames(dtj_java_consumer_t *jc, jobject stack,
1599     jobjectArray frames)
1600 {
1601 	JNIEnv *jenv = jc->dtjj_jenv;
1602 
1603 	if ((*jenv)->IsInstanceOf(jenv, stack, g_stack_jc)) {
1604 		(*jenv)->CallVoidMethod(jenv, stack, g_stackset_frames_jm,
1605 		    frames);
1606 	} else if ((*jenv)->IsInstanceOf(jenv, stack, g_ustack_jc)) {
1607 		(*jenv)->CallVoidMethod(jenv, stack, g_ustackset_frames_jm,
1608 		    frames);
1609 	}
1610 }
1611 
1612 static void
1613 dtj_attach_name(dtj_java_consumer_t *jc, jobject symbol, jstring s)
1614 {
1615 	JNIEnv *jenv = jc->dtjj_jenv;
1616 
1617 	if ((*jenv)->IsInstanceOf(jenv, symbol, g_symbol_jc)) {
1618 		(*jenv)->CallVoidMethod(jenv, symbol, g_symbolset_name_jm, s);
1619 	} else if ((*jenv)->IsInstanceOf(jenv, symbol, g_usymbol_jc)) {
1620 		(*jenv)->CallVoidMethod(jenv, symbol, g_usymbolset_name_jm, s);
1621 	}
1622 }
1623 
1624 /*
1625  * Note: It is not valid to look outside the current libdtrace record in the
1626  * given aggdata (except to get the aggregation ID from the first record).
1627  *
1628  * Return DTRACE_HANDLE_ABORT if java exception pending, otherwise
1629  * DTRACE_HANDLE_OK.
1630  */
1631 static int
1632 dtj_agghandler(const dtrace_bufdata_t *bufdata, dtj_java_consumer_t *jc)
1633 {
1634 	JNIEnv *jenv = jc->dtjj_jenv;
1635 
1636 	const dtrace_aggdata_t *aggdata = bufdata->dtbda_aggdata;
1637 	const dtrace_aggdesc_t *aggdesc;
1638 	const dtrace_recdesc_t *rec = bufdata->dtbda_recdesc;
1639 	const char *s = bufdata->dtbda_buffered;
1640 	dtrace_actkind_t act = DTRACEACT_NONE;
1641 	int64_t aggid;
1642 
1643 	jobject jobj = NULL;
1644 
1645 	if (aggdata == NULL) {
1646 		/* Assert without crashing */
1647 		dtj_throw_illegal_state(jenv, "null aggdata");
1648 		WRAP_EXCEPTION(jenv);
1649 		return (DTRACE_HANDLE_ABORT);
1650 	}
1651 	aggdesc = aggdata->dtada_desc;
1652 
1653 	/*
1654 	 * Get the aggregation ID from the first record.
1655 	 */
1656 	/* LINTED - alignment */
1657 	aggid = *((int64_t *)(aggdata->dtada_data +
1658 	    aggdesc->dtagd_rec[0].dtrd_offset));
1659 	if (aggid < 0) {
1660 		/* Assert without crashing */
1661 		dtj_throw_illegal_argument(jenv, "negative aggregation ID");
1662 		WRAP_EXCEPTION(jenv);
1663 		return (DTRACE_HANDLE_ABORT);
1664 	}
1665 
1666 	if (jc->dtjj_consumer->dtjc_printa_snaptime) {
1667 		/* Append buffered output if this is a printa() callback. */
1668 		jstring jstr = dtj_NewStringNative(jenv, s);
1669 		if ((*jenv)->ExceptionCheck(jenv)) {
1670 			WRAP_EXCEPTION(jenv);
1671 			return (DTRACE_HANDLE_ABORT);
1672 		}
1673 		/*
1674 		 * StringBuilder append() returns a reference to the
1675 		 * StringBuilder; must not leak the returned reference.
1676 		 */
1677 		jobj = (*jenv)->CallObjectMethod(jenv,
1678 		    jc->dtjj_printa_buffer, g_buf_append_str_jm, jstr);
1679 		(*jenv)->DeleteLocalRef(jenv, jstr);
1680 		(*jenv)->DeleteLocalRef(jenv, jobj);
1681 		if ((*jenv)->ExceptionCheck(jenv)) {
1682 			WRAP_EXCEPTION(jenv);
1683 			return (DTRACE_HANDLE_ABORT);
1684 		}
1685 	} else {
1686 		/*
1687 		 * Test whether to include the aggregation if this is a
1688 		 * getAggregate() call.  Optimization: perform the inclusion
1689 		 * test only when the aggregation has changed.
1690 		 */
1691 		if (aggid != jc->dtjj_consumer->dtjc_aggid) {
1692 			jc->dtjj_consumer->dtjc_included =
1693 			    dtj_is_included(aggdata, jc);
1694 			if ((*jenv)->ExceptionCheck(jenv)) {
1695 				WRAP_EXCEPTION(jenv);
1696 				return (DTRACE_HANDLE_ABORT);
1697 			}
1698 		}
1699 		if (!jc->dtjj_consumer->dtjc_included) {
1700 			return (DTRACE_HANDLE_OK);
1701 		}
1702 	}
1703 	jc->dtjj_consumer->dtjc_aggid = aggid;
1704 
1705 	/*
1706 	 * Determine the expected number of tuple members.  While it is not
1707 	 * technically valid to look outside the current record in the current
1708 	 * aggdata, this implementation does so without a known failure case.
1709 	 * Any method relying only on the current callback record makes riskier
1710 	 * assumptions and still does not cover every corner case (for example,
1711 	 * counting the records from index 1 up to and not including the index
1712 	 * of the current DTRACE_BUFDATA_AGGVAL record, which fails when a
1713 	 * format string specifies the value ahead of one or more tuple
1714 	 * elements).  Knowing that the calculation of the expected tuple size
1715 	 * is technically invalid (because it looks outside the current record),
1716 	 * we make the calculation at the earliest opportunity, before anything
1717 	 * might happen to invalidate any part of the aggdata.  It ought to be
1718 	 * safe in any case: dtrd_action and dtrd_size do not appear ever to be
1719 	 * overwritten, and dtrd_offset is not used outside the current record.
1720 	 *
1721 	 * It is possible (if the assumptions here ever prove untrue) that the
1722 	 * libdtrace buffered output handler may need to be enhanced to provide
1723 	 * the expected number of tuple members.
1724 	 */
1725 	if (jc->dtjj_consumer->dtjc_expected < 0) {
1726 		int r;
1727 		for (r = 1; r < aggdesc->dtagd_nrecs; ++r) {
1728 			act = aggdesc->dtagd_rec[r].dtrd_action;
1729 			if (DTRACEACT_ISAGG(act) ||
1730 			    aggdesc->dtagd_rec[r].dtrd_size == 0) {
1731 				break;
1732 			}
1733 		}
1734 		jc->dtjj_consumer->dtjc_expected = r - 1;
1735 	}
1736 
1737 	if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGKEY) {
1738 		/* record value is a tuple member */
1739 
1740 		if (jc->dtjj_tuple == NULL) {
1741 			jc->dtjj_tuple = (*jenv)->NewObject(jenv,
1742 			    g_tuple_jc, g_tupleinit_jm);
1743 			if (!jc->dtjj_tuple) {
1744 				/* java exception pending */
1745 				return (DTRACE_HANDLE_ABORT);
1746 			}
1747 		}
1748 
1749 		act = rec->dtrd_action;
1750 
1751 		switch (act) {
1752 		case DTRACEACT_STACK:
1753 		case DTRACEACT_USTACK:
1754 		case DTRACEACT_JSTACK:
1755 			jobj = dtj_new_tuple_stack_record(aggdata, rec, s, jc);
1756 			break;
1757 		case DTRACEACT_USYM:
1758 		case DTRACEACT_UADDR:
1759 		case DTRACEACT_UMOD:
1760 		case DTRACEACT_SYM:
1761 		case DTRACEACT_MOD:
1762 			jobj = dtj_new_tuple_symbol_record(aggdata, rec, s, jc);
1763 			break;
1764 		default:
1765 			jobj = dtj_recdata(jc, rec->dtrd_size,
1766 			    (aggdata->dtada_data + rec->dtrd_offset));
1767 		}
1768 
1769 		if (!jobj) {
1770 			/* java exception pending */
1771 			return (DTRACE_HANDLE_ABORT);
1772 		}
1773 
1774 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_tuple,
1775 		    g_tupleadd_jm, jobj);
1776 		(*jenv)->DeleteLocalRef(jenv, jobj);
1777 		if ((*jenv)->ExceptionCheck(jenv)) {
1778 			WRAP_EXCEPTION(jenv);
1779 			return (DTRACE_HANDLE_ABORT);
1780 		}
1781 	} else if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGVAL) {
1782 		/*
1783 		 * Record value is that of an aggregating action.  The printa()
1784 		 * format string may place the tuple ahead of the aggregation
1785 		 * value(s), so we can't be sure we have the tuple until we get
1786 		 * the AGGLAST flag indicating the last callback associated with
1787 		 * the current tuple.  Save the aggregation value or values
1788 		 * (multiple values if more than one aggregation is passed to
1789 		 * printa()) until then.
1790 		 */
1791 		dtj_aggval_t *aggval;
1792 
1793 		jstring jvalue = NULL;
1794 
1795 		jvalue = dtj_new_aggval(jc, aggdata, rec);
1796 		if (!jvalue) {
1797 			/* java exception pending */
1798 			WRAP_EXCEPTION(jenv);
1799 			return (DTRACE_HANDLE_ABORT);
1800 		}
1801 		aggval = dtj_aggval_create(jenv, jvalue, aggdesc->dtagd_name,
1802 		    aggid);
1803 		if (!aggval) {
1804 			/* OutOfMemoryError pending */
1805 			(*jenv)->DeleteLocalRef(jenv, jvalue);
1806 			return (DTRACE_HANDLE_ABORT);
1807 		}
1808 		if (!dtj_list_add(jc->dtjj_aggval_list, aggval)) {
1809 			/* deletes jvalue reference */
1810 			dtj_aggval_destroy(aggval, jenv);
1811 			dtj_throw_out_of_memory(jenv, "Failed to add aggval");
1812 			return (DTRACE_HANDLE_ABORT);
1813 		}
1814 	}
1815 
1816 	if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGLAST) {
1817 		/* No more values associated with the current tuple. */
1818 
1819 		dtj_aggval_t *aggval;
1820 		uu_list_walk_t *itr;
1821 		int tuple_member_count;
1822 
1823 		jobject jrec = NULL;
1824 		jstring jname = NULL;
1825 
1826 		if (jc->dtjj_consumer->dtjc_expected == 0) {
1827 			/*
1828 			 * singleton aggregation declared in D with no square
1829 			 * brackets
1830 			 */
1831 			jc->dtjj_tuple = (*jenv)->GetStaticObjectField(jenv,
1832 			    g_tuple_jc, g_tuple_EMPTY_jsf);
1833 			if (jc->dtjj_tuple == NULL) {
1834 				dtj_throw_out_of_memory(jenv,
1835 				    "Failed to reference Tuple.EMPTY");
1836 				return (DTRACE_HANDLE_ABORT);
1837 			}
1838 		}
1839 
1840 		if (jc->dtjj_tuple == NULL) {
1841 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1842 			    g_pdatainvalidate_printa_jm);
1843 			goto printa_output;
1844 		}
1845 
1846 		tuple_member_count = (*jenv)->CallIntMethod(jenv,
1847 		    jc->dtjj_tuple, g_tuplesize_jm);
1848 		if (tuple_member_count <
1849 		    jc->dtjj_consumer->dtjc_expected) {
1850 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1851 			    g_pdatainvalidate_printa_jm);
1852 			(*jenv)->DeleteLocalRef(jenv, jc->dtjj_tuple);
1853 			jc->dtjj_tuple = NULL;
1854 			goto printa_output;
1855 		}
1856 
1857 		itr = uu_list_walk_start(jc->dtjj_aggval_list, 0);
1858 		while ((aggval = uu_list_walk_next(itr)) != NULL) {
1859 			/*
1860 			 * new AggregationRecord:  Combine the aggregation value
1861 			 * with the saved tuple and add it to the current
1862 			 * Aggregate or PrintaRecord.
1863 			 */
1864 			jrec = (*jenv)->NewObject(jenv, g_aggrec_jc,
1865 			    g_aggrecinit_jm, jc->dtjj_tuple,
1866 			    aggval->dtja_value);
1867 			(*jenv)->DeleteLocalRef(jenv, aggval->dtja_value);
1868 			aggval->dtja_value = NULL;
1869 			if (!jrec) {
1870 				/* java exception pending */
1871 				WRAP_EXCEPTION(jenv);
1872 				return (DTRACE_HANDLE_ABORT);
1873 			}
1874 
1875 			/* aggregation name */
1876 			jname = (*jenv)->NewStringUTF(jenv,
1877 			    aggval->dtja_aggname);
1878 			if (!jname) {
1879 				/* OutOfMemoryError pending */
1880 				(*jenv)->DeleteLocalRef(jenv, jrec);
1881 				return (DTRACE_HANDLE_ABORT);
1882 			}
1883 
1884 			/*
1885 			 * If the printa() format string specifies the value of
1886 			 * the aggregating action multiple times, PrintaRecord
1887 			 * ignores the attempt to add the duplicate record.
1888 			 */
1889 			if (jc->dtjj_consumer->dtjc_printa_snaptime) {
1890 				/* add to PrintaRecord */
1891 				(*jenv)->CallVoidMethod(jenv,
1892 				    jc->dtjj_probedata,
1893 				    g_pdataadd_aggrec_jm,
1894 				    jname, aggval->dtja_aggid, jrec);
1895 			} else {
1896 				/* add to Aggregate */
1897 				(*jenv)->CallVoidMethod(jenv,
1898 				    jc->dtjj_aggregate, g_aggaddrec_jm,
1899 				    jname, aggval->dtja_aggid, jrec);
1900 			}
1901 
1902 			(*jenv)->DeleteLocalRef(jenv, jrec);
1903 			(*jenv)->DeleteLocalRef(jenv, jname);
1904 			if ((*jenv)->ExceptionCheck(jenv)) {
1905 				WRAP_EXCEPTION(jenv);
1906 				return (DTRACE_HANDLE_ABORT);
1907 			}
1908 		}
1909 		uu_list_walk_end(itr);
1910 		dtj_list_clear(jc->dtjj_aggval_list, dtj_aggval_destroy,
1911 		    jenv);
1912 
1913 printa_output:
1914 		if (jc->dtjj_consumer->dtjc_printa_snaptime) {
1915 			/*
1916 			 * Get the formatted string associated with the current
1917 			 * tuple if this is a printa() callback.
1918 			 */
1919 			jstring jstr = (*jenv)->CallObjectMethod(jenv,
1920 			    jc->dtjj_printa_buffer, g_tostring_jm);
1921 			if ((*jenv)->ExceptionCheck(jenv)) {
1922 				WRAP_EXCEPTION(jenv);
1923 				return (DTRACE_HANDLE_ABORT);
1924 			}
1925 			/*
1926 			 * Clear the StringBuilder: this does not throw
1927 			 * exceptions.  Reuse the StringBuilder until the end of
1928 			 * the current probedata then dispose of it.
1929 			 */
1930 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_printa_buffer,
1931 			    g_bufsetlen_jm, 0);
1932 			/* Add formatted string to PrintaRecord */
1933 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1934 			    g_pdataadd_printa_str_jm, jc->dtjj_tuple, jstr);
1935 			(*jenv)->DeleteLocalRef(jenv, jstr);
1936 			if ((*jenv)->ExceptionCheck(jenv)) {
1937 				WRAP_EXCEPTION(jenv);
1938 				return (DTRACE_HANDLE_ABORT);
1939 			}
1940 		}
1941 
1942 		(*jenv)->DeleteLocalRef(jenv, jc->dtjj_tuple);
1943 		jc->dtjj_tuple = NULL;
1944 		jc->dtjj_consumer->dtjc_expected = -1;
1945 	}
1946 
1947 	return (DTRACE_HANDLE_OK);
1948 }
1949 
1950 /*
1951  * Return B_TRUE if the aggregation is included, B_FALSE otherwise.  Only in the
1952  * latter case might there be an exception pending.
1953  */
1954 static boolean_t
1955 dtj_is_included(const dtrace_aggdata_t *data, dtj_java_consumer_t *jc)
1956 {
1957 	JNIEnv *jenv = jc->dtjj_jenv;
1958 
1959 	if (jc->dtjj_aggregate_spec) {
1960 		jboolean included;
1961 		jstring aggname = NULL;
1962 
1963 		const dtrace_aggdesc_t *aggdesc = data->dtada_desc;
1964 		aggname = (*jenv)->NewStringUTF(jenv, aggdesc->dtagd_name);
1965 		if (!aggname) {
1966 			/* java exception pending */
1967 			return (B_FALSE);
1968 		}
1969 
1970 		included = (*jenv)->CallBooleanMethod(jenv,
1971 		    jc->dtjj_aggregate_spec, g_aggspec_included_jm,
1972 		    aggname);
1973 		(*jenv)->DeleteLocalRef(jenv, aggname);
1974 		if ((*jenv)->ExceptionCheck(jenv)) {
1975 			WRAP_EXCEPTION(jenv);
1976 			return (B_FALSE);
1977 		}
1978 
1979 		return (included);
1980 	}
1981 
1982 	return (B_TRUE);
1983 }
1984 
1985 /*
1986  * Return NULL if a java exception is pending, otherwise return a new
1987  * AggregationValue instance.
1988  */
1989 static jobject
1990 dtj_new_aggval(dtj_java_consumer_t *jc, const dtrace_aggdata_t *data,
1991     const dtrace_recdesc_t *rec)
1992 {
1993 	JNIEnv *jenv = jc->dtjj_jenv;
1994 
1995 	jobject jvalue = NULL; /* return value */
1996 
1997 	dtrace_actkind_t act;
1998 	uint64_t normal;
1999 	caddr_t addr;
2000 	int64_t value;
2001 
2002 	act = rec->dtrd_action;
2003 	normal = data->dtada_normal;
2004 	addr = data->dtada_data + rec->dtrd_offset;
2005 	if (act == DTRACEAGG_AVG) {
2006 		value = dtj_average(addr, normal);
2007 	} else {
2008 		/* LINTED - alignment */
2009 		value = (*((int64_t *)addr)) / normal;
2010 	}
2011 
2012 	if (act == DTRACEAGG_QUANTIZE || act == DTRACEAGG_LQUANTIZE) {
2013 		jvalue = dtj_new_distribution(data, rec, jc);
2014 	} else {
2015 		switch (act) {
2016 		case DTRACEAGG_COUNT:
2017 			jvalue = (*jenv)->NewObject(jenv, g_aggcount_jc,
2018 			    g_aggcountinit_jm, value);
2019 			break;
2020 		case DTRACEAGG_SUM:
2021 			jvalue = (*jenv)->NewObject(jenv, g_aggsum_jc,
2022 			    g_aggsuminit_jm, value);
2023 			break;
2024 		case DTRACEAGG_AVG:
2025 			jvalue = (*jenv)->NewObject(jenv, g_aggavg_jc,
2026 			    g_aggavginit_jm, value, dtj_avg_total(addr,
2027 			    normal), dtj_avg_count(addr));
2028 			break;
2029 		case DTRACEAGG_MIN:
2030 			jvalue = (*jenv)->NewObject(jenv, g_aggmin_jc,
2031 			    g_aggmininit_jm, value);
2032 			break;
2033 		case DTRACEAGG_MAX:
2034 			jvalue = (*jenv)->NewObject(jenv, g_aggmax_jc,
2035 			    g_aggmaxinit_jm, value);
2036 			break;
2037 		case DTRACEAGG_STDDEV:
2038 			jvalue = dtj_stddev(jenv, addr, normal);
2039 			break;
2040 		default:
2041 			jvalue = NULL;
2042 			dtj_throw_illegal_argument(jenv,
2043 			    "unexpected aggregation action: %d", act);
2044 		}
2045 	}
2046 
2047 	return (jvalue);
2048 }
2049 
2050 /*
2051  * Stops the given consumer if it is running.  Throws DTraceException if
2052  * dtrace_stop() fails and no other exception is already pending.  Clears and
2053  * rethrows any pending exception in order to grab the global lock safely.
2054  */
2055 void
2056 dtj_stop(dtj_java_consumer_t *jc)
2057 {
2058 	JNIEnv *jenv;
2059 	int rc;
2060 	jthrowable e;
2061 
2062 	switch (jc->dtjj_consumer->dtjc_state) {
2063 	case DTJ_CONSUMER_GO:
2064 	case DTJ_CONSUMER_START:
2065 		break;
2066 	default:
2067 		return;
2068 	}
2069 
2070 	jenv = jc->dtjj_jenv;
2071 	e = (*jenv)->ExceptionOccurred(jenv);
2072 	if (e) {
2073 		(*jenv)->ExceptionClear(jenv);
2074 	}
2075 
2076 	(*jenv)->MonitorEnter(jenv, g_caller_jc);
2077 	if ((*jenv)->ExceptionCheck(jenv)) {
2078 		goto rethrow;
2079 	}
2080 
2081 	rc = dtrace_status(jc->dtjj_consumer->dtjc_dtp);
2082 	if (rc != DTRACE_STATUS_STOPPED) {
2083 		rc = dtrace_stop(jc->dtjj_consumer->dtjc_dtp);
2084 	}
2085 
2086 	(*jenv)->MonitorExit(jenv, g_caller_jc);
2087 	if ((*jenv)->ExceptionCheck(jenv)) {
2088 		goto rethrow;
2089 	}
2090 
2091 	if (rc == -1) {
2092 		(*jenv)->MonitorEnter(jenv, g_caller_jc);
2093 		if ((*jenv)->ExceptionCheck(jenv)) {
2094 			goto rethrow;
2095 		}
2096 		/* Do not wrap DTraceException */
2097 		dtj_throw_dtrace_exception(jc,
2098 		    "couldn't stop tracing: %s",
2099 		    dtrace_errmsg(jc->dtjj_consumer->dtjc_dtp,
2100 		    dtrace_errno(jc->dtjj_consumer->dtjc_dtp)));
2101 		/* safe to call with pending exception */
2102 		(*jenv)->MonitorExit(jenv, g_caller_jc);
2103 	} else {
2104 		jc->dtjj_consumer->dtjc_state = DTJ_CONSUMER_STOP;
2105 	}
2106 
2107 rethrow:
2108 	if (e) {
2109 		if ((*jenv)->ExceptionCheck(jenv)) {
2110 			/*
2111 			 * Favor earlier pending exception over
2112 			 * exception thrown in this function.
2113 			 */
2114 			(*jenv)->ExceptionClear(jenv);
2115 		}
2116 		(*jenv)->Throw(jenv, e);
2117 		(*jenv)->DeleteLocalRef(jenv, e);
2118 	}
2119 }
2120 
2121 /*
2122  * Return Aggregate instance, or null if java exception pending.
2123  */
2124 jobject
2125 dtj_get_aggregate(dtj_java_consumer_t *jc)
2126 {
2127 	JNIEnv *jenv = jc->dtjj_jenv;
2128 	hrtime_t snaptime;
2129 	int rc;
2130 
2131 	jobject aggregate = NULL;
2132 
2133 	/* Must not call MonitorEnter with a pending exception */
2134 	if ((*jenv)->ExceptionCheck(jenv)) {
2135 		WRAP_EXCEPTION(jenv);
2136 		return (NULL);
2137 	}
2138 
2139 	/*
2140 	 * Aggregations must be snapped, walked, and cleared atomically,
2141 	 * otherwise clearing loses data accumulated since the most recent snap.
2142 	 * This per-consumer lock prevents dtrace_work() from snapping or
2143 	 * clearing aggregations while we're in the middle of this atomic
2144 	 * operation, so we continue to hold it until done clearing.
2145 	 */
2146 	(*jenv)->MonitorEnter(jenv, jc->dtjj_consumer_lock);
2147 	if ((*jenv)->ExceptionCheck(jenv)) {
2148 		WRAP_EXCEPTION(jenv);
2149 		return (NULL);
2150 	}
2151 
2152 	dtj_aggwalk_init(jc);
2153 	if ((*jenv)->ExceptionCheck(jenv)) {
2154 		WRAP_EXCEPTION(jenv);
2155 		/* release per-consumer lock */
2156 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2157 		return (NULL);
2158 	}
2159 
2160 	/*
2161 	 * Snap aggregations
2162 	 *
2163 	 * We need to record the snaptime here for the caller.  Leaving it to
2164 	 * the caller to record the snaptime before calling getAggregate() may
2165 	 * be inaccurate because of the indeterminate delay waiting on the
2166 	 * consumer lock before calling dtrace_aggregate_snap().
2167 	 */
2168 	snaptime = gethrtime();
2169 	if (dtrace_aggregate_snap(jc->dtjj_consumer->dtjc_dtp) != 0) {
2170 		dtj_error_t e;
2171 
2172 		/*
2173 		 * The dataDropped() ConsumerListener method can throw an
2174 		 * exception in the getAggregate() thread if the drop handler is
2175 		 * invoked during dtrace_aggregate_snap().
2176 		 */
2177 		if ((*jenv)->ExceptionCheck(jenv)) {
2178 			/* Do not wrap exception thrown from ConsumerListener */
2179 			/* release per-consumer lock */
2180 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2181 			return (NULL);
2182 		}
2183 
2184 		if (dtj_get_dtrace_error(jc, &e) == DTJ_OK) {
2185 			/* Do not wrap DTraceException */
2186 			dtj_throw_dtrace_exception(jc, e.dtje_message);
2187 		}
2188 		/* release per-consumer lock */
2189 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2190 		return (NULL);
2191 	}
2192 
2193 	if ((*jenv)->ExceptionCheck(jenv)) {
2194 		/*
2195 		 * Wrap the exception thrown from ConsumerListener in this case,
2196 		 * so we can see that it unexpectedly reached this spot in
2197 		 * native code (dtrace_aggregate_snap should have returned
2198 		 * non-zero).
2199 		 */
2200 		WRAP_EXCEPTION(jenv);
2201 		/* release per-consumer lock */
2202 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2203 		return (NULL);
2204 	}
2205 
2206 	/* Create the Java representation of the aggregate snapshot. */
2207 	aggregate = (*jenv)->NewObject(jenv, g_agg_jc, g_agginit_jm,
2208 	    snaptime);
2209 	if ((*jenv)->ExceptionCheck(jenv)) {
2210 		WRAP_EXCEPTION(jenv);
2211 		/* release per-consumer lock */
2212 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2213 		return (NULL);
2214 	}
2215 	jc->dtjj_aggregate = aggregate;
2216 
2217 	/*
2218 	 * Walk the aggregate, converting the data into Java Objects. Traverse
2219 	 * in the order determined by libdtrace, respecting the various
2220 	 * "aggsort" options, just as dtrace_work does when generating
2221 	 * aggregations for the printa() action. libdtrace ordering is preserved
2222 	 * in the "ordinal" property of AggregationRecord, since it would
2223 	 * otherwise be lost when the records are hashed into the Aggregation's
2224 	 * map. Neither the consumer loop nor the competing getAggregate()
2225 	 * thread should depend on any particular record ordering (such as
2226 	 * ordering by tuple key) to process records correctly.
2227 	 *
2228 	 * It is impractical to hold the global lock around
2229 	 * dtrace_aggregate_print(), since it may take a long time (e.g. an
2230 	 * entire second) if it performs expensive conversions such as that
2231 	 * needed for user stack traces.  Most libdtrace functions are not
2232 	 * guaranteed to be MT-safe, even when each thread has its own dtrace
2233 	 * handle; or even if they are safe, there is no guarantee that future
2234 	 * changes may not make them unsafe.  Fortunately in this case, however,
2235 	 * only a per-consumer lock is necessary to avoid conflict with
2236 	 * dtrace_work() running in another thread (the consumer loop).
2237 	 */
2238 	rc = dtrace_aggregate_print(jc->dtjj_consumer->dtjc_dtp, NULL, NULL);
2239 	if ((*jenv)->ExceptionCheck(jenv)) {
2240 		WRAP_EXCEPTION(jenv);
2241 		/* release per-consumer lock */
2242 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2243 		return (NULL);
2244 	}
2245 	if (rc != 0) {
2246 		dtj_error_t e;
2247 		if (dtj_get_dtrace_error(jc, &e) != DTJ_OK) {
2248 			/* release per-consumer lock */
2249 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2250 			return (NULL);
2251 		}
2252 
2253 		if (e.dtje_number != EINTR) {
2254 			/* Do not wrap DTraceException */
2255 			dtj_throw_dtrace_exception(jc, e.dtje_message);
2256 			/* release per-consumer lock */
2257 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2258 			return (NULL);
2259 		}
2260 	}
2261 
2262 	dtj_aggwalk_init(jc);
2263 	if ((*jenv)->ExceptionCheck(jenv)) {
2264 		WRAP_EXCEPTION(jenv);
2265 		/* release per-consumer lock */
2266 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2267 		return (NULL);
2268 	}
2269 
2270 	/*
2271 	 * dtrace_aggregate_clear() clears all aggregations, and we need to
2272 	 * clear aggregations selectively.  It also fails to preserve the
2273 	 * lquantize() range and step size; using aggregate_walk() to clear
2274 	 * aggregations does not have this problem.
2275 	 */
2276 	rc = dtrace_aggregate_walk(jc->dtjj_consumer->dtjc_dtp, dtj_clear, jc);
2277 	if ((*jenv)->ExceptionCheck(jenv)) {
2278 		WRAP_EXCEPTION(jenv);
2279 		/* release per-consumer lock */
2280 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2281 		return (NULL);
2282 	}
2283 	if (rc != 0) {
2284 		dtj_error_t e;
2285 		if (dtj_get_dtrace_error(jc, &e) == DTJ_OK) {
2286 			/* Do not wrap DTraceException */
2287 			dtj_throw_dtrace_exception(jc, e.dtje_message);
2288 		}
2289 		/* release per-consumer lock */
2290 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2291 		return (NULL);
2292 	}
2293 
2294 	(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2295 	if ((*jenv)->ExceptionCheck(jenv)) {
2296 		WRAP_EXCEPTION(jenv);
2297 		return (NULL);
2298 	}
2299 
2300 	aggregate = jc->dtjj_aggregate;
2301 	jc->dtjj_aggregate = NULL;
2302 
2303 	return (aggregate);
2304 }
2305 
2306 /*
2307  * Process any requests, such as the setting of runtime options, enqueued during
2308  * dtrace_sleep().  A Java exception is pending if this function returns
2309  * DTJ_ERR.
2310  */
2311 static dtj_status_t
2312 dtj_process_requests(dtj_java_consumer_t *jc)
2313 {
2314 	dtj_request_t *r;
2315 	uu_list_t *list = jc->dtjj_consumer->dtjc_request_list;
2316 	pthread_mutex_t *list_lock = &jc->dtjj_consumer->
2317 	    dtjc_request_list_lock;
2318 	const char *opt;
2319 	const char *val;
2320 
2321 	(void) pthread_mutex_lock(list_lock);
2322 	while (!dtj_list_empty(list)) {
2323 		r = uu_list_first(list);
2324 		uu_list_remove(list, r);
2325 
2326 		switch (r->dtjr_type) {
2327 		case DTJ_REQUEST_OPTION:
2328 			opt = dtj_string_list_first(r->dtjr_args);
2329 			val = dtj_string_list_last(r->dtjr_args);
2330 			if (dtrace_setopt(jc->dtjj_consumer->dtjc_dtp, opt,
2331 			    val) == -1) {
2332 				/* Do not wrap DTraceException */
2333 				dtj_throw_dtrace_exception(jc,
2334 				    "failed to set %s: %s", opt,
2335 				    dtrace_errmsg(jc->dtjj_consumer->dtjc_dtp,
2336 				    dtrace_errno(jc->dtjj_consumer->dtjc_dtp)));
2337 				dtj_request_destroy(r, NULL);
2338 				(void) pthread_mutex_unlock(list_lock);
2339 				return (DTJ_ERR);
2340 			}
2341 			break;
2342 		}
2343 		dtj_request_destroy(r, NULL);
2344 	}
2345 	(void) pthread_mutex_unlock(list_lock);
2346 	return (DTJ_OK);
2347 }
2348 
2349 /*
2350  * Return DTJ_OK if the consumer loop is stopped normally by either the exit()
2351  * action or the Consumer stop() method.  Otherwise return DTJ_ERR if the
2352  * consumer loop terminates abnormally with an exception pending.
2353  */
2354 dtj_status_t
2355 dtj_consume(dtj_java_consumer_t *jc)
2356 {
2357 	JNIEnv *jenv = jc->dtjj_jenv;
2358 	dtrace_hdl_t *dtp = jc->dtjj_consumer->dtjc_dtp;
2359 	boolean_t done = B_FALSE;
2360 	dtj_error_t e;
2361 
2362 	do {
2363 		if (!jc->dtjj_consumer->dtjc_interrupt) {
2364 			dtrace_sleep(dtp);
2365 		}
2366 
2367 		if (jc->dtjj_consumer->dtjc_interrupt) {
2368 			done = B_TRUE;
2369 			dtj_stop(jc);
2370 			if ((*jenv)->ExceptionCheck(jenv)) {
2371 				/*
2372 				 * Exception left pending by Consumer
2373 				 * getAggregate() method.
2374 				 */
2375 				return (DTJ_ERR);
2376 			}
2377 		} else if (jc->dtjj_consumer->dtjc_process_list != NULL) {
2378 			int nprocs = uu_list_numnodes(jc->dtjj_consumer->
2379 			    dtjc_process_list);
2380 			if (jc->dtjj_consumer->dtjc_procs_ended == nprocs) {
2381 				done = B_TRUE;
2382 				dtj_stop(jc);
2383 			}
2384 		}
2385 
2386 		/*
2387 		 * Functions like dtrace_setopt() are not safe to call during
2388 		 * dtrace_sleep().  Check the request list every time we wake up
2389 		 * from dtrace_sleep().
2390 		 */
2391 		if (!done) {
2392 			if (dtj_process_requests(jc) != DTJ_OK) {
2393 				/* Do not wrap DTraceException */
2394 				return (DTJ_ERR);
2395 			}
2396 		}
2397 
2398 		/* Must not call MonitorEnter with a pending exception */
2399 		if ((*jenv)->ExceptionCheck(jenv)) {
2400 			WRAP_EXCEPTION(jenv);
2401 			return (DTJ_ERR);
2402 		}
2403 
2404 		/*
2405 		 * Use the per-consumer lock to avoid conflict with
2406 		 * get_aggregate() called from another thread.
2407 		 */
2408 		(*jenv)->MonitorEnter(jenv, jc->dtjj_consumer_lock);
2409 		if ((*jenv)->ExceptionCheck(jenv)) {
2410 			WRAP_EXCEPTION(jenv);
2411 			return (DTJ_ERR);
2412 		}
2413 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller,
2414 		    g_interval_began_jm);
2415 		if ((*jenv)->ExceptionCheck(jenv)) {
2416 			/* Don't wrap exception thrown from ConsumerListener */
2417 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2418 			return (DTJ_ERR);
2419 		}
2420 		jc->dtjj_consumer->dtjc_printa_snaptime = gethrtime();
2421 		switch (dtrace_work(dtp, NULL, dtj_chew, dtj_chewrec, jc)) {
2422 		case DTRACE_WORKSTATUS_DONE:
2423 			done = B_TRUE;
2424 			break;
2425 		case DTRACE_WORKSTATUS_OKAY:
2426 			break;
2427 		default:
2428 			/*
2429 			 * Check for a pending exception that got us to this
2430 			 * error workstatus case.
2431 			 */
2432 			if ((*jenv)->ExceptionCheck(jenv)) {
2433 				/*
2434 				 * Ensure valid initial state before releasing
2435 				 * the consumer lock
2436 				 */
2437 				jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2438 				/* Do not wrap DTraceException */
2439 				/* Release per-consumer lock */
2440 				(*jenv)->MonitorExit(jenv,
2441 				    jc->dtjj_consumer_lock);
2442 				return (DTJ_ERR);
2443 			}
2444 
2445 			if (dtj_get_dtrace_error(jc, &e) != DTJ_OK) {
2446 				/* java exception pending */
2447 				jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2448 				/* Release per-consumer lock */
2449 				(*jenv)->MonitorExit(jenv,
2450 				    jc->dtjj_consumer_lock);
2451 				return (DTJ_ERR);
2452 			}
2453 
2454 			if (e.dtje_number != EINTR) {
2455 				/* Do not wrap DTraceException */
2456 				dtj_throw_dtrace_exception(jc, e.dtje_message);
2457 				jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2458 				/* Release per-consumer lock */
2459 				(*jenv)->MonitorExit(jenv,
2460 				    jc->dtjj_consumer_lock);
2461 				return (DTJ_ERR);
2462 			}
2463 		}
2464 		/*
2465 		 * Check for ConsumerException before doing anything else with
2466 		 * the JNIEnv.
2467 		 */
2468 		if ((*jenv)->ExceptionCheck(jenv)) {
2469 			/*
2470 			 * Do not wrap exception thrown from ConsumerListener.
2471 			 */
2472 			jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2473 			/* Release per-consumer lock */
2474 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2475 			return (DTJ_ERR);
2476 		}
2477 		jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2478 		/*
2479 		 * Notify ConsumerListeners the the dtrace_work() interval ended
2480 		 * before releasing the lock.
2481 		 */
2482 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller,
2483 		    g_interval_ended_jm);
2484 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2485 		if ((*jenv)->ExceptionCheck(jenv)) {
2486 			/* Don't wrap exception thrown from ConsumerListener */
2487 			return (DTJ_ERR);
2488 		}
2489 
2490 		/*
2491 		 * Check for a temporarily cleared exception set by a handler
2492 		 * that could not safely leave the exception pending because it
2493 		 * could not return an abort signal.  Rethrow it now that it's
2494 		 * safe to do so (when it's possible to ensure that no JNI calls
2495 		 * will be made that are unsafe while an exception is pending).
2496 		 */
2497 		if (jc->dtjj_exception) {
2498 			(*jenv)->Throw(jenv, jc->dtjj_exception);
2499 			(*jenv)->DeleteLocalRef(jenv, jc->dtjj_exception);
2500 			jc->dtjj_exception = NULL;
2501 			return (DTJ_ERR);
2502 		}
2503 	} while (!done);
2504 
2505 	return (DTJ_OK);
2506 }
2507