blob: 3f2259353d1e6f22f86f087755248b8928397e45 [file] [log] [blame]
<!--
TODO:
- Add tooltips for *all* options?
- Implement "none" option for turning agents off?
-->
<!DOCTYPE html>
<!--
Copyright (c) 2017, 2020 IBM Corp. and others
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution and is available at http://eclipse.org/legal/epl-2.0 or the Apache License, Version 2.0 which accompanies this distribution and is available at https://www.apache.org/licenses/LICENSE-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License, version 2 with the GNU Classpath Exception [1] and GNU General Public License, version 2 with the OpenJDK Assembly Exception [2].
[1] https://www.gnu.org/software/classpath/license.html
[2] http://openjdk.java.net/legal/assembly-exception.html
SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
The project website pages cannot be redistributed
-->
<html>
<title>Xdump Option Builder</title>
<head>
<script type="text/javascript" language="JavaScript">
var compatibleEventElementIds = {};
compatibleEventElementIds["vmstop"] = ["event_vmstop", "event_vmstop_filter"];
compatibleEventElementIds["load"] = ["event_load", "event_unload", "event_class_filter"];
compatibleEventElementIds["unload"] = ["event_load", "event_unload", "event_class_filter"];
compatibleEventElementIds["throw"] = ["event_throw", "event_catch", "event_uncaught", "event_systhrow", "event_throwable_class", "event_throwable_method", "event_throwable_msg_filter"];
compatibleEventElementIds["catch"] = ["event_throw", "event_catch", "event_uncaught", "event_systhrow", "event_throwable_class", "event_throwable_method", "event_throwable_msg_filter"];
compatibleEventElementIds["uncaught"] = ["event_throw", "event_catch", "event_uncaught", "event_systhrow", "event_throwable_class", "event_throwable_method", "event_throwable_msg_filter"];
compatibleEventElementIds["systhrow"] = ["event_throw", "event_catch", "event_uncaught", "event_systhrow", "event_throwable_class", "event_throwable_method", "event_throwable_msg_filter"];
compatibleEventElementIds["allocation"] = ["event_allocation", "event_allocation_filter_size_min", "event_allocation_filter_units_min", "event_allocation_filter_size_max", "event_allocation_filter_units_max"];
compatibleEventElementIds["slow"] = ["event_slow", "event_slow_filter"];
var filterElementIds = {};
filterElementIds["vmstop"] = ["event_vmstop_filter"];
filterElementIds["load"] = ["event_class_filter"];
filterElementIds["unload"] = ["event_class_filter"];
filterElementIds["throw"] = ["event_throwable_class", "event_throwable_method", "event_throwable_msg_filter", "event_throwable_offset"];
filterElementIds["catch"] = ["event_throwable_class", "event_throwable_method", "event_throwable_msg_filter", "event_throwable_offset"];
filterElementIds["uncaught"] = ["event_throwable_class", "event_throwable_method", "event_throwable_msg_filter", "event_throwable_offset"];
filterElementIds["systhrow"] = ["event_throwable_class", "event_throwable_method", "event_throwable_msg_filter", "event_throwable_offset"];
filterElementIds["allocation"] = ["event_allocation_filter_size_min", "event_allocation_filter_units_min", "event_allocation_filter_size_max", "event_allocation_filter_units_max"];
filterElementIds["slow"] = ["event_slow_filter"];
var agentsRequiringRequest = {};
agentsRequiringRequest["serial"] = ["snap", "jit", "ceedump"];
agentsRequiringRequest["exclusive"] = ["heap", "system", "java", "snap", "jit", "console", "ceedump"];
agentsRequiringRequest["prepwalk"] = ["heap", "system"];
agentsRequiringRequest["preempt"] = ["java"];
var noHeapdumpEventElementIds = ["event_gpf", "event_traceassert", "event_abort"];
var agentsThatDumpAFileIds = ["agent_system", "agent_java", "agent_heap", "agent_snap", "agent_jit"];
var fileDsnTokenTargetElement = null;
var toolExecMouseDown = false;
document.addEventListener("mouseup", clearToolExecMouseDown);
function initialSetup() {
setupTooltips();
parseParams();
}
function setupTooltips() {
var titleText;
titleText = "Filter on the fully qualified name of the Exception (or Error) class, to reduce the number of dump files " +
"produced. Use slashes as package separators. Asterisks as wildcards are supported at the beginning of " +
"the string, and/or at the end if no method filter is specified. Examples:\n\n" +
" - java/lang/OutOfMemoryError\n" +
" - *IOException";
document.getElementById("event_throwable_class").title = titleText;
titleText = "Filter on a fully qualified method name to reduce the number of dump files produced. The default stack frame " +
"offset is 0, which is the top stack frame - i.e. the method from which the Exception was thrown.\n\n" +
"Use slashes as package separators. Asterisks as wildcards are supported at the end of the string. Examples:\n\n" +
" - java/lang/String.getBytes*\n" +
" - java/util/*";
document.getElementById("event_throwable_method").title = titleText;
titleText = "Filter on text within the exception message, to reduce the number of dump files produced. Asterisks as " +
"wildcards are supported at the beginning and/or end of the string. Examples:\n\n" +
" - *class format*\n" +
" - *access denied*\n";
document.getElementById("event_throwable_msg_filter").title = titleText;
titleText = "The stack frame offset allows you to specify the position of the filtered method in the stack. This option is " +
"useful if the exception is being thrown from a general purpose or utility class. " +
"The default value is 0 (i.e. the top stack frame)";
document.getElementById("event_throwable_offset").title = titleText;
titleText = "Filter on the fully qualified Class name, to reduce the number of dump files produced. Asterisks " +
"as wildcards are supported at the beginning or end of the string. Use slashes as package separators. Examples:\n\n" +
" - java/lang/String" +
" - java/util/Hash*" +
" - *security*";
document.getElementById("event_class_filter").title = titleText;
titleText = "One event can generate multiple dumps. The agents that produce each dump run sequentially and their order is " +
"determined by the priority keyword set for each agent. Higher priority dump agents are started first. The " +
"priorities associated with default dump agents can be viewed by running \"java -Xdump:what\".";
document.getElementById("priority").title = titleText;
titleText = "Specify the range of dump events on which to trigger the specified dump agents. For example, if \"First event\" is set to 5, " +
"and \"Last event\" set to 7, the dump event will trigger only on the 5th, 6th and 7th dump events. A value of 0 means " +
"\"no limit\"\n\n" +
"The default is first = 1 and last = 0 except for when the shell command (tool) agent is enabled, whereby the default " +
" becomes first = 1 and last = 1.";
document.getElementById("range_li").title = titleText;
titleText = "The exit agent is only supported from OpenJ9 release 0.18.0 and up.";
document.getElementById("agent_exit_li").title = titleText;
}
function parseParams() {
// Note that this code, and the corresponding serialization code in
// copyLinkToClipboard(), relies on the order of the inputs in the
// document to work correctly.
// Elements that can be enabled/disabled automatically must come *after*
// the elements which control that behaviour. If not, the default values
// will override the serialized values.
if (location.search != "") {
// Get the query part of the URL, remove the leading '?', and split on '&'
var params = location.search.substring(1).split("&"); // this includes the '?' so need to substring it
for (var i = 0; i < params.length; i++) {
var param = params[i].split("=");
var key = param[0];
var value = param[1];
var element = document.getElementById(param[0]);
if (element == null) {
console.log("ERROR: Key does not map to element: " + key);
continue; // Go to the next parameter
}
switch (element.type) {
case "checkbox":
switch (value) {
case "0":
element.checked = false;
break;
case "1":
element.checked = true;
break;
default:
console.log("ERROR: Invalid value for checkbox element \"" + element.id + "\": " + value);
continue; // Go to the next parameter
}
break;
case "text":
element.value = decodeURIComponent(value);
break;
case "number":
element.value = value;
break;
}
processChange(element);
element.blur();
}
} else {
// If no parameters were provided, just build the result with the defaults
buildAndUpdateResult();
}
}
function processChange(option) {
if (option.name == "agent") {
if (option.value == "tool") {
var execFieldElement = document.getElementById("exec");
var toolAsyncElement = document.getElementById("tool_async");
var toolWaitElement = document.getElementById("tool_wait");
var rangeElement = document.getElementById("range");
var rangeFirstElement = document.getElementById("range_first");
var rangeLastElement = document.getElementById("range_last");
if (option.checked == true) {
// If range has not been modified, set it to the tool default of 1..1
if (rangeFirstElement.value == 1 && rangeLastElement.value == 0) {
rangeFirstElement.value = 1;
rangeLastElement.value = 1;
}
enableInput(execFieldElement);
enableInput(toolAsyncElement);
enableInput(toolWaitElement);
execFieldElement.focus();
// Tool agent is only compatible with the exit agent, so disable all the other agent inputs
var agentInputElements = document.getElementById("agent_input").getElementsByTagName("input");
for (var i = 0; i < agentInputElements.length; i++) {
if (agentInputElements[i].id.match(/^agent_/) != null && agentInputElements[i].id != "agent_tool" && agentInputElements[i].id != "agent_exit") {
disableInput(agentInputElements[i]);
}
}
} else {
// If range has not been modified, set it to the normal default of 1..0
if (rangeFirstElement.value == 1 && rangeLastElement.value == 1) {
rangeFirstElement.value = 1;
rangeLastElement.value = 0;
}
disableInput(execFieldElement);
disableInput(toolAsyncElement);
disableInput(toolWaitElement);
// Enable all agent inputs now that the tool agent is unchecked
var agentInputElements = document.getElementById("agent_input").getElementsByTagName("input");
for (var i = 0; i < agentInputElements.length; i++) {
if (agentInputElements[i].id.match(/^agent_/) != null) {
enableInput(agentInputElements[i]);
}
}
}
}
// The tool agent is only compatible with the exit agent
if (option.value != "tool" && option.value != "exit") {
if (option.checked == true) {
// Disable tool if any agent other than exit is checked
disableInput(document.getElementById("agent_tool"));
} else {
// Enable tool if no other agents are checked, or only exit is checked
var agentInputElements = document.getElementById("agent_input").getElementsByTagName("input");
var enableToolAgent = true;
for (var i = 0; i < agentInputElements.length; i++) {
if (agentInputElements[i].id.match(/^agent_/) != null && agentInputElements[i].id != "agent_exit" && agentInputElements[i].checked) {
enableToolAgent = false;
break;
}
}
if (enableToolAgent) {
enableInput(document.getElementById("agent_tool"));
}
}
}
configureRequestOptions(option.value);
}
// Prepwalk can only be checked if exclusive access is also checked
if (option.value == "prepwalk") {
// Exclusive access must be checked if prepwalk is checked
if (option.checked == true) {
document.getElementById("request_exclusive").checked = true;
}
} else if (option.value == "exclusive") {
// If exclusive access gets unchecked, uncheck prepwalk
if (option.checked == false) {
document.getElementById("request_prepwalk").checked = false;
}
}
// Enable range number fields when range is checked
if (option.name == "range") {
if (option.checked == true) {
enableInput(document.getElementById("range_first"));
enableInput(document.getElementById("range_last"));
} else {
disableInput(document.getElementById("range_first"));
disableInput(document.getElementById("range_last"));
}
}
// Set a sensible default value for the range fields if the user enters an empty value
if (option.name == "range_first") {
if (option.value == "") {
option.value = 1;
}
} else if (option.name == "range_last") {
if (option.value == "") {
option.value = 0;
}
}
// Fix obvious mistakes in class name filters
if (option.name == "throwable_class" || option.name == "class_text") {
// Remove any whitespace
option.value = option.value.replace(/\s/g,'');
// Replace dots with slashes
option.value = option.value.replace(/\./g, "/");
}
// Attempt to correct common formatting mistakes in the method filter
if (option.name == "throwable_method") {
// Remove any whitespace
option.value = option.value.replace(/\s/g,'');
// Check for more than one dot in the string
if (option.value.indexOf(".") != -1 && (option.value.indexOf(".") != option.value.lastIndexOf("."))) {
// Replace dots with slashes until there is only one dot left
// This is a best effort, and isn't always going to work
while (option.value.indexOf(".") != option.value.lastIndexOf(".")) {
option.value = option.value.replace(".", "/");
}
}
}
// Enable/disable events that are incompatible with the one that has been changed
if (option.name == "event") {
if (option.getAttribute("data-hasfilter") == "true") {
if (option.checked == true) {
// Disable events that are not compatible with this event
disableIncompatibleEventElements(compatibleEventElementIds[option.value]);
// Enable relevant filters
var filterIds = filterElementIds[option.value];
for (var i = 0; i < filterIds.length; i++) {
enableInput(document.getElementById(filterIds[i]));
}
} else { // Event has been unchecked
var compatibleEventIds = compatibleEventElementIds[option.value];
var compatibleEventChecked = false;
// Check whether any events that are compatible with this one are still checked
for (var i = 0; i < compatibleEventIds.length; i++) {
if (document.getElementById(compatibleEventIds[i]).type == "checkbox" && document.getElementById(compatibleEventIds[i]).checked) {
compatibleEventChecked = true;
}
}
// If no compatible events are checked, enable *all* events and disable filter(s) associated with this event
if (!compatibleEventChecked) {
enableEventElementsWithFilters(option);
var filterIds = filterElementIds[option.value];
for (var i = 0; i < filterIds.length; i++) {
disableInput(document.getElementById(filterIds[i]));
}
}
}
}
}
// If event_throw is checked, automatically check event_systhrow as well
if (option.name == "event" && option.value == "throw" && option.checked == true) {
document.getElementById("event_systhrow").checked = true;
}
// The gpf, traceassert, and abort events cannot trigger a heap dump,
// prepare the heap (request=prepwalk), or compact the heap (request=compact)
if (heapIncompatibleEventChecked() && !heapCompatibleEventChecked()) {
disableInput(document.getElementById("agent_heap"));
disableInput(document.getElementById("request_prepwalk"));
disableInput(document.getElementById("request_compact"));
} else {
// The heap agent is not compatible with the tool agent, so only enable heap if tool is not in use
var toolAgentElement = document.getElementById("agent_tool");
if (toolAgentElement.disabled || !toolAgentElement.checked) {
enableInput(document.getElementById("agent_heap"));
}
enableInput(document.getElementById("request_prepwalk"));
enableInput(document.getElementById("request_compact"));
}
// Enable/disable file text field
var fileTextElement = document.getElementById("file_text");
var enableTokenButtons = false;
if (fileCompatibleAgentChecked()) {
enableInput(fileTextElement);
enableTokenButtons = true;
} else {
disableInput(fileTextElement);
}
// Enable/disable dsn text field
var dsnTextElement = document.getElementById("dsn_text");
if (document.getElementById("agent_system").checked) {
enableInput(dsnTextElement);
enableTokenButtons = true;
} else {
disableInput(dsnTextElement);
}
// Enable/disable file/dsn token buttons
if (enableTokenButtons) {
enableDumpNameTokenButtons();
} else {
disableDumpNameTokenButtons();
}
// Insert text in the target text input if one of the token buttons is pressed
if (option.type == "button") {
if (option.getAttribute("data-target") == null && fileDsnTokenTargetElement != null) {
insertText(fileDsnTokenTargetElement, option.getAttribute("data-token"));
} else {
insertText(document.getElementById(option.getAttribute("data-target")), option.getAttribute("data-token"));
}
}
// Remove focus from input element (ensures error styling works correctly)
if (option.id != null) {
option.blur();
}
// Build the result string and display it
buildAndUpdateResult();
}
// Check/uncheck recommended request options when the specified agent has been changed
function configureRequestOptions(agent) {
var requestsToConfigure = Object.keys(agentsRequiringRequest);
for (var i = 0; i < requestsToConfigure.length; i++) {
if (agentNeedsRequest(agent, requestsToConfigure[i])) {
if (document.getElementById("agent_" + agent).checked == true) {
document.getElementById("request_" + requestsToConfigure[i]).checked = true;
} else if (!enabledAgentsNeedRequest(requestsToConfigure[i])) {
document.getElementById("request_" + requestsToConfigure[i]).checked = false;
}
}
}
}
// Returns true if the specified agent should run with the specified request option
// Otherwise returns false
function agentNeedsRequest(agent, request) {
var agentsForRequest = agentsRequiringRequest[request];
for (var i = 0; i < agentsForRequest.length; i++) {
if (agent == agentsForRequest[i]) {
return true;
}
}
return false;
}
// Returns true if any enabled agents should run with the specified request option
// Otherwise returns false
function enabledAgentsNeedRequest(request) {
var agentsForRequest = agentsRequiringRequest[request];
for (var i = 0; i < agentsForRequest.length; i++) {
if (document.getElementById("agent_" + agentsForRequest[i]).checked) {
return true;
}
}
return false;
}
function heapCompatibleEventChecked() {
var section = document.getElementById("event_input");
var elements = section.getElementsByTagName("input");
for (var i = 0; i < elements.length; i++) {
if (elements[i].checked) {
// This element is checked - check whether it is a heap-compatible event
var isCompatibleEvent = true;
for (var j = 0; j < noHeapdumpEventElementIds.length; j++) {
if (elements[i].id == noHeapdumpEventElementIds[j]) {
isCompatibleEvent = false;
}
}
if (isCompatibleEvent) {
return true;
}
}
}
// If we reach here, no heap-compatible events were checked
return false;
}
function heapIncompatibleEventChecked() {
for (var i = 0; i < noHeapdumpEventElementIds.length; i++) {
if (document.getElementById(noHeapdumpEventElementIds[i]).checked) {
return true;
}
}
return false;
}
function fileCompatibleAgentChecked() {
for (var i = 0; i < agentsThatDumpAFileIds.length; i++) {
if (document.getElementById(agentsThatDumpAFileIds[i]).checked) {
return true;
}
}
}
function disableIncompatibleEventElements(compatibleEventElementIds) {
// need to pass an array so we can deal with throw/systhrow etc.
var section = document.getElementById("event_input");
var elements = section.getElementsByTagName("input");
for (var i = 0; i < elements.length; i++) {
if (elements[i].getAttribute("data-hasfilter") == "true" || elements[i].type == "text") {
var compatible = false;
for (var j = 0; j < compatibleEventElementIds.length; j++) {
if (elements[i].id == compatibleEventElementIds[j]) {
compatible = true;
}
}
if (!compatible) {
disableInput(elements[i]);
}
}
}
}
function enableEventElementsWithFilters() {
var section = document.getElementById("event_input");
var elements = section.getElementsByTagName("input");
for (var i = 0; i < elements.length; i++) {
if (elements[i].type == "checkbox" && elements[i].getAttribute("data-hasfilter") == "true") {
enableInput(elements[i]);
}
}
}
function disableInput(inputElement) {
// Disable the input itself
inputElement.disabled = true;
// Disable associated labels, if any
var labelElements = getLabelsForInput(inputElement);
if (typeof labelElements != undefined && labelElements != null) {
for (var i = 0; i < labelElements.length; i++) {
labelElements[i].setAttribute("data-disabled", "true");
}
}
// Disable associated buttons, if any
var buttonElements = getButtonsForInput(inputElement);
if (typeof buttonElements != undefined && buttonElements != null) {
for (var i = 0; i < buttonElements.length; i++) {
buttonElements[i].disabled = true;
}
}
}
function enableInput(inputElement) {
// Enable the input itself
inputElement.disabled = false;
// Enable associated labels, if any
var labelElements = getLabelsForInput(inputElement);
if (typeof labelElements != undefined && labelElements != null) {
for (var i = 0; i < labelElements.length; i++) {
labelElements[i].setAttribute("data-disabled", "false");
}
}
// Enable associated buttons, if any
var buttonElements = getButtonsForInput(inputElement);
if (typeof buttonElements != undefined && buttonElements != null) {
for (var i = 0; i < buttonElements.length; i++) {
buttonElements[i].disabled = false;
}
}
}
function enableDumpNameTokenButtons() {
var allInputs = document.getElementsByTagName("input");
for (var i = 0; i < allInputs.length; i++) {
if (allInputs[i].id.indexOf("file_button_") != -1) {
allInputs[i].disabled = false;
}
}
}
function disableDumpNameTokenButtons() {
var allInputs = document.getElementsByTagName("input");
for (var i = 0; i < allInputs.length; i++) {
if (allInputs[i].id.indexOf("file_button_") != -1) {
allInputs[i].disabled = true;
}
}
}
function getLabelsForInput(inputElement) {
var allLabels = document.getElementsByTagName("label");
var results = [];
for (var i = 0; i < allLabels.length; i++) {
if (inputElement.id == allLabels[i].htmlFor) {
results.push(allLabels[i]);
}
}
return results;
}
function getButtonsForInput(inputElement) {
var allInputs = document.getElementsByTagName("input");
var results = [];
for (var i = 0; i < allInputs.length; i++) {
if (allInputs[i].type == "button" && allInputs[i].getAttribute("data-target") == inputElement.id) {
results.push(allInputs[i]);
}
}
return results;
}
function buildAndUpdateResult() {
var resultString = "-Xdump:";
var agentString = "";
var eventString = "";
var filterString = "";
// Agents
var section = document.getElementById("agent_input");
var agentElements = section.getElementsByTagName("input");
for (var i = 0; i < agentElements.length; i++) {
if (!agentElements[i].disabled && agentElements[i].checked == true && agentElements[i].id != "tool_async") {
if (agentString != "") {
agentString += "+";
}
agentString += agentElements[i].value;
}
}
if (agentString != "") {
resultString += agentString;
}
// Events and filters
var eventSection = document.getElementById("event_input");
var eventElements = eventSection.getElementsByTagName("input");
// Need to make sure filters are only added once for throw/systhrow, load/unload etc.
var filterAdded = {};
for (var i = 0; i < eventElements.length; i++) {
if (eventElements[i].name != "event") {
// If it's not an event it's a filter - mark it as not added yet
filterAdded[eventElements[i]] = false;
}
}
for (var i = 0; i < eventElements.length; i++) {
if (eventElements[i].name == "event" && eventElements[i].checked == true) {
if (eventString != "") {
eventString += "+";
}
eventString += eventElements[i].value;
// Filters
if (eventElements[i].getAttribute("data-hasfilter") == "true") {
var filterIds = filterElementIds[eventElements[i].value];
for (var j = 0; j < filterIds.length; j++ ) {
var tempString = document.getElementById(filterIds[j]).value;
if (tempString == "" || filterAdded[filterIds[j]]) {
// Filter is empty or has already been added
continue;
}
// Get contents of filters and augment/correct if necessary
if (filterIds[j] == "event_throwable_class") {
filterString += tempString;
} else if (filterIds[j] == "event_throwable_method") {
filterString += "#" + tempString;
} else if (filterIds[j] == "event_throwable_msg_filter") {
// Do nothing. This is added to the result under a separate flag later on.
} else if (filterIds[j] == "event_throwable_offset") {
if (tempString != "0" && document.getElementById("event_throwable_method").value != "") {
filterString += "#" + tempString;
} else {
continue;
}
} else if (filterIds[j] == "event_vmstop_filter") {
filterString += "#" + tempString;
} else if (filterIds[j] == "event_slow_filter") {
filterString += "#" + tempString + "ms";
} else if (filterIds[j] == "event_allocation_filter_size_min") {
filterString += "#" + tempString;
} else if (filterIds[j] == "event_allocation_filter_size_max") {
filterString += ".." + tempString;
} else if (filterIds[j] == "event_allocation_filter_units_min" && document.getElementById("event_allocation_filter_size_min").value == "") {
// Don't add units if size is empty
} else if (filterIds[j] == "event_allocation_filter_units_max" && document.getElementById("event_allocation_filter_size_max").value == "") {
// Don't add units if size is empty
} else {
// Can add the filter value as-is for all other filters
filterString += tempString;
}
filterAdded[filterIds[j]] = true;
}
}
}
}
if (eventString != "") {
resultString += ":events=" + eventString;
}
if (filterString != "") {
resultString += ",filter=" + filterString;
}
// msg_filter
var messageFilterStringElement = document.getElementById("event_throwable_msg_filter");
if (messageFilterStringElement.disabled == false && messageFilterStringElement.value != "") {
resultString += ",msg_filter=" + messageFilterStringElement.value;
}
// range
var rangeFirst = document.getElementById("range_first").value;
var rangeLast = document.getElementById("range_last").value;
if (document.getElementById("agent_tool").checked) {
// Default with "tool" agent enabled is 1..1
if (rangeFirst != 1 || rangeLast != 1) {
resultString += ",range=" + rangeFirst + ".." + rangeLast;
}
} else {
// Normal default is 1..0
if (rangeFirst != 1 || rangeLast != 0) {
resultString += ",range=" + rangeFirst + ".." + rangeLast;
}
}
// priority
var priority = document.getElementById("priority").value;
if (priority != "") {
resultString += ",priority=" + priority;
}
// exec
if (document.getElementById("agent_tool").checked) {
var execString = document.getElementById("exec").value;
if (execString != "") {
resultString += ",exec=" + execString;
}
// opts
var optsString = "";
var toolAsyncElement = document.getElementById("tool_async");
var toolWaitElement = document.getElementById("tool_wait");
if (toolAsyncElement.checked) {
optsString += toolAsyncElement.value;
}
if (toolWaitElement.value != 0) {
if (optsString != "") {
optsString += "+";
}
optsString += "WAIT" + toolWaitElement.value;
}
if (optsString != "") {
resultString += ",opts=" + optsString;
}
}
// request
var requestSection = document.getElementById("request_input");
var requestElements = requestSection.getElementsByTagName("input");
var requestString = "";
for (var i = 0; i < requestElements.length; i++) {
if (!requestElements[i].disabled && requestElements[i].checked) {
if (requestElements[i].value != "preempt" || (requestElements[i].value == "preempt" && document.getElementById("agent_java").checked == true)) {
if (requestString != "") {
requestString += "+";
}
requestString += requestElements[i].value;
}
}
}
if (requestString != "") {
resultString += ",request=" + requestString;
}
// Dump file name
var fileElement = document.getElementById("file_text");
if (!fileElement.disabled) {
if (fileElement.value != "") {
resultString += ",file=" + fileElement.value;
}
}
// SYSTDUMP data set name
var dsnElement = document.getElementById("dsn_text");
if (!dsnElement.disabled) {
if (dsnElement.value != "") {
resultString += ",dsn=" + dsnElement.value;
}
}
// Wrap in quotes if option checked
if (document.getElementById("wrap_in_quotes").checked) {
// Escape backslashes
resultString = resultString.replace(/\\/g, "\\\\");
// Escape quotes
resultString = resultString.replace(/"/g, "\\\"");
// Wrap the entire result string in quotes
resultString = "\"" + resultString + "\"";
}
// Escape HTML characters
resultString = escapeHTML(resultString);
// Add <wbr> tags after '+', ','. '/' and '=' characters
// to make the wrapping prettier for longer options
resultString = resultString.replace(/,/g, ",<wbr>");
resultString = resultString.replace(/\+/g, "+<wbr>");
resultString = resultString.replace(/\//g, "/<wbr>");
resultString = resultString.replace(/=/g, "=<wbr>");
// Rudimentry checks for validity of result
var resultIsGreen = true;
var errorsHtml = "";
var warningsHtml = "";
// Check whether any dump events are selected
if (eventString == "") {
resultIsGreen = false;
errorsHtml += "ERROR: No dump event selected<br>";
}
// Check whether any dump agents are selected
if (agentString == "") {
resultIsGreen = false;
errorsHtml += "ERROR: No dump agent selected<br>";
}
// Check object allocation filter sizes
var minimumSizeElement = document.getElementById("event_allocation_filter_size_min");
var maximumSizeElement = document.getElementById("event_allocation_filter_size_max");
if (document.getElementById("event_allocation").checked) {
// Minimum must be specified, it must be greater than or equal to 0, and it must be less than the maximum
if (minimumSizeElement.value == "" || minimumSizeElement.value < 0 || (maximumSizeElement.value != "" && minimumSizeElement.value > maximumSizeElement.value)) {
resultIsGreen = false;
setErrorStyle(minimumSizeElement);
errorsHtml += "ERROR: Invalid minimum size for object allocation size filter: must be >= 0, and must be < maximum size<br>";
} else {
unsetErrorStyle(minimumSizeElement);
}
// Maxmimum can be omitted, but if it is specified it must be greater than zero, and greater than the minimum.
if (maximumSizeElement.value != "" && (maximumSizeElement.value <= 0 || (minimumSizeElement.value != "" && minimumSizeElement.value > maximumSizeElement.value))) {
resultIsGreen = false;
setErrorStyle(maximumSizeElement);
errorsHtml += "ERROR: Invalid maximum size for object allocation size filter: must be > 0, and must be > minimum size<br>";
} else {
unsetErrorStyle(maximumSizeElement);
}
} else {
// Ensure error styling is removed if this option is unchecked
unsetErrorStyle(minimumSizeElement);
unsetErrorStyle(maximumSizeElement);
}
// Check that a command has been specified if the tool agent is selected
var execElement = document.getElementById("exec");
if (document.getElementById("agent_tool").checked && execElement != document.activeElement && !toolExecMouseDown) {
if (execElement.value == "") {
resultIsGreen = false;
setErrorStyle(execElement);
errorsHtml += "ERROR: Shell command (tool) agent is checked, but no shell command has been specified<br>";
} else if (execElement.value.indexOf(",") != -1) {
resultIsGreen = false;
setErrorStyle(execElement);
errorsHtml += "ERROR: Invalid shell command: must not contain a comma.<br>";
} else {
unsetErrorStyle(execElement);
}
} else {
unsetErrorStyle(execElement);
}
// Check value provided for tool wait time
var toolWaitElement = document.getElementById("tool_wait");
if (!toolWaitElement.disabled && toolWaitElement.value < 0) {
resultIsGreen = false;
setErrorStyle(toolWaitElement);
errorsHtml += "ERROR: Invalid tool wait time: must be > 0<br>";
} else {
unsetErrorStyle(toolWaitElement);
}
// Check validity of the throwable class filter. Rules:
// 1. Can start with a wildcard character
// 2. Can end with a wildcard character if no method filter is specified
// 3. Can contain just a single wildcard character on its own
// 4. Cannot contain a wildcard in any other location
// 5. Cannot contain a comma
var throwableClassHasError = false;
var throwableClassElement = document.getElementById("event_throwable_class")
if (!throwableClassElement.disabled) {
var classValue = throwableClassElement.value;
if (classValue.lastIndexOf("*") > 0) {
if (classValue.indexOf("*", 1) != (classValue.length - 1)) {
throwableClassHasError = true;
errorsHtml += "ERROR: Invalid Exception class filter: wildcards can only be used at the beginning and/or end of the filter<br>";
} else if (document.getElementById("event_throwable_method").value != "") {
throwableClassHasError = true
errorsHtml += "ERROR: Invalid Exception class filter: must not end with a wildcard when a method filter is specified<br>";
}
}
if (classValue.indexOf(",") != -1) {
throwableClassHasError = true;
errorsHtml += "ERROR: Invalid Exception class filter: must not contain a comma.<br>";
}
if (throwableClassHasError) {
resultIsGreen = false;
setErrorStyle(throwableClassElement);
} else {
unsetErrorStyle(throwableClassElement);
}
}
// Check validity of the throwable method filter. Rules:
// 1. Can end with a wildcard character if no stack offset is specified
// 2. Cannot contain a wildcard in any other location
// 3. Cannot contain a comma
var throwableMethodHasError = false;
var throwableMethodElement = document.getElementById("event_throwable_method");
if (!throwableMethodElement.disabled) {
var methodValue = throwableMethodElement.value;
var wildcardIndex = methodValue.indexOf("*");
if (wildcardIndex != -1) {
if (wildcardIndex != (methodValue.length - 1)) {
throwableMethodHasError = true;
errorsHtml += "ERROR: Invalid Exception method filter: wildcard can only be used at the end of the filter<br>";
} else if (document.getElementById("event_throwable_offset").value != "0") {
throwableMethodHasError = true;
errorsHtml += "ERROR: Invalid Exception method filter: must not end with a wildcard when using a non-zero stack offset.<br>";
}
}
if (methodValue.indexOf(",") != -1) {
throwableMethodHasError = true;
errorsHtml += "ERROR: Invalid Exception method filter: must not contain a comma.<br>";
}
if (throwableMethodHasError) {
resultIsGreen = false;
setErrorStyle(throwableMethodElement);
} else {
unsetErrorStyle(throwableMethodElement);
}
}
// Check validity of the throwable message filter string
var throwableMessageElement = document.getElementById("event_throwable_msg_filter");
if (throwableMessageElement.value.indexOf(",") != -1) {
resultIsGreen = false;
setErrorStyle(throwableMessageElement);
errorsHtml += "ERROR: Invalid Exception message filter: must not contain a comma.<br>";
} else {
unsetErrorStyle(throwableMessageElement);
}
// Check validity of the class load/unload filter string
var classFilterElement = document.getElementById("event_class_filter");
if (classFilterElement.value.indexOf(",") != -1) {
resultIsGreen = false;
setErrorStyle(classFilterElement);
errorsHtml += "ERROR: Invalid class load/unload filter: must not contain a comma.<br>";
} else {
unsetErrorStyle(classFilterElement);
}
// Dump filename checks
var dumpFileTextElement = document.getElementById("file_text");
if (!dumpFileTextElement.disabled && dumpFileTextElement.value != "") {
if (dumpFileTextElement.value.indexOf(",") != -1) {
resultIsGreen = false;
setErrorStyle(dumpFileTextElement);
errorsHtml += "ERROR: Invalid dump file pattern: must not contain a comma.<br>";
} else {
unsetErrorStyle(dumpFileTextElement);
}
if (containsReservedChars(dumpFileTextElement.value)) {
warningsHtml += "WARNING: Dump file pattern contains a character that is disallowed on some platforms<br>";
}
} else {
unsetErrorStyle(dumpFileTextElement);
}
// SYSTDUMP data set name checks
var datasetTextElement = document.getElementById("dsn_text");
if (!datasetTextElement.disabled && datasetTextElement.value != "") {
if (datasetTextElement.value.indexOf(",") != -1) {
resultIsGreen = false;
setErrorStyle(datasetTextElement);
errorsHtml += "ERROR: Invalid data set pattern: must not contain a comma.<br>";
} else {
unsetErrorStyle(datasetTextElement);
}
if (dumpFileTextElement.value != "") {
var ok = false;
for (var i = 0; i < agentsThatDumpAFileIds.length; i++) {
if (agentsThatDumpAFileIds[i] != "agent_system" && document.getElementById(agentsThatDumpAFileIds[i]).checked) {
ok = true;
}
}
if (!ok) {
resultIsGreen = false;
setErrorStyle(datasetTextElement);
setErrorStyle(dumpFileTextElement);
errorsHtml += "ERROR: File and data set patterns cannot both be specified when only system dumps are being generated.<br>";
}
}
if (containsReservedChars(datasetTextElement.value)) {
warningsHtml += "WARNING: Data set pattern contains a character that is disallowed on some platforms<br>";
}
} else {
unsetErrorStyle(datasetTextElement);
}
// Check the dump priority value
var priorityElement = document.getElementById("priority");
if (priorityElement.value < 0 || priorityElement.value > 999) {
resultIsGreen = false;
setErrorStyle(priorityElement);
errorsHtml += "ERROR: Invalid dump priority value: must be > 0 and < 999<br>";
} else {
unsetErrorStyle(priorityElement);
}
// Check whether any incompatible events/agents are selected
// (nearly all incompatible scenarios are prevented by enabling/disabling input fields)
if (heapIncompatibleEventChecked()) {
if (!document.getElementById("agent_heap").disabled && document.getElementById("agent_heap").checked) {
warningsHtml += "WARNING: The PHD heap dump agent cannot be triggered by GPF, abort, or internal JVM error events<br>";
}
if (!document.getElementById("request_prepwalk").disabled && document.getElementById("request_prepwalk").checked) {
warningsHtml += "WARNING: Dump agents triggered by a GPF, abort, or internal JVM error cannot ensure the heap is walkable prior to dumping<br>";
}
if (!document.getElementById("request_compact").disabled && document.getElementById("request_compact").checked) {
warningsHtml += "WARNING: Dump agents triggered by a GPF, abort, or internal JVM error cannot conduct a global GC prior to dumping<br>";
}
if (!document.getElementById("request_exclusive").disabled && document.getElementById("request_exclusive").checked) {
warningsHtml += "WARNING: Dump agents triggered by a GPF, abort, or internal JVM error may have problems obtaining exclusive JVM access<br>";
}
}
// Add the result string in the appropriate colour
if (resultIsGreen) {
document.getElementById("result").innerHTML = "<font color=\"green\">" + resultString + "</font>";
} else {
document.getElementById("result").innerHTML = "<font color=\"red\">" + resultString + "</font>";
}
// Add errors/warnings, if any
if (errorsHtml != "" || warningsHtml != "") {
document.getElementById("errors").innerHTML = errorsHtml + warningsHtml;
} else {
document.getElementById("errors").innerHTML = "&nbsp;";
}
}
// Return true if a string contains characters that are reserved on some platforms
// Otherwise return false
function containsReservedChars(string) {
if ( string.indexOf("\\") != -1
|| string.indexOf("/") != -1
|| string.indexOf(":") != -1
|| string.indexOf("*") != -1
|| string.indexOf("?") != -1
|| string.indexOf("\"") != -1
|| string.indexOf("<") != -1
|| string.indexOf(">") != -1
|| string.indexOf("|") != -1
) {
return true;
} else {
return false;
}
}
function setErrorStyle(inputElement) {
inputElement.style.borderColor = "red";
inputElement.style.borderStyle = "solid";
}
function unsetErrorStyle(inputElement) {
inputElement.style.borderColor = "";
inputElement.style.borderStyle = "";
inputElement.style.borderColor = null;
inputElement.style.borderStyle = null;
}
function escapeHTML(text) {
return text.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// If a string ends with a '&' remove it
function removeFinalAmpersandIfPresent(string) {
if (string.length > 0 && string.lastIndexOf("&") == string.length - 1) {
return string.slice(0, -1);
} else {
return string;
}
}
// Register this text element as the target for the dsn/file token buttons
function registerTokenTarget(textFieldElement) {
fileDsnTokenTargetElement = textFieldElement;
}
// Register when a mousedown event has occurred on a tool/exec element
function registerToolExecMouseDown() {
toolExecMouseDown = true;
}
// Register when a mousedown event has finished
function clearToolExecMouseDown() {
toolExecMouseDown = false;
}
// Inserts text in a target text input, replacing the current selected text
// Target field must be enabled
function insertText(targetElement, textToInsert) {
if (targetElement.disabled) {
return;
}
var oldTextValue = targetElement.value;
var selectionStart = targetElement.selectionStart;
var selectionEnd = targetElement.selectionEnd;
// Get text before/after current selection
var textBeforeSelection = oldTextValue.substring(0, selectionStart);
var textAfterSelection = oldTextValue.substring(selectionEnd, oldTextValue.length);
// Insert text, effectively replacing the current selection
targetElement.value = textBeforeSelection + textToInsert + textAfterSelection;
// Set cursor position to the end of the inserted text
var cursorPosition = selectionStart + textToInsert.length;
// Make sure nothing is selected
targetElement.selectionStart = cursorPosition;
targetElement.selectionEnd = cursorPosition;
// Give focus to the target field
targetElement.focus();
}
function copyTextToClipboard(element) {
var selection = window.getSelection(); // get the window's Selection object
selection.removeAllRanges(); // deselect any user selected text
// Create a temporary element and store the target element's text in it
// (while stripping out any HTML tags)
var tempElement = document.createElement("p");
tempElement.innerText = element.innerText;
// Append temporary element to the DOM so we can copy its contents
document.body.appendChild(tempElement);
var range = document.createRange(); // create a new range object
range.selectNodeContents(tempElement); // set range to cover target element text
selection.addRange(range); // add range to Selection object
document.execCommand("copy"); // do the copy
selection.removeAllRanges(); // deselect the target element's text
// Remove the temporary text area
tempElement.parentNode.removeChild(tempElement);
}
function copyLinkToClipboard() {
// Serialize the form input fields
// Note that this code, and the corresponding deserialization code in
// parseParams(), relies on the order of the inputs in the document to
// work correctly.
// Elements that can be enabled/disabled automatically must come *after*
// the elements which control that behaviour. If not, the default values
// will override the serialized values.
var serializedForm = "";
var inputs = document.getElementById("XdumpForm").getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
var inputElement = inputs[i];
if (inputElement.type == "checkbox") {
if (inputElement.checked) {
serializedForm += inputElement.id + "=1&";
} else if (inputElement.id == "event_systhrow" || inputElement.id.lastIndexOf("request_") == 0) {
// These specific checkboxes can be checked automatically if certain other
// options are checked, so if they're unchecked we need to make note.
serializedForm += inputElement.id + "=0&";
}
}
if (inputElement.type == "text" && inputElement.value != "") {
serializedForm += inputElement.id + "=" + encodeURIComponent(inputElement.value) + "&";
}
if (inputElement.type == "number") {
serializedForm += inputElement.id + "=" + inputElement.value + "&";
}
}
serializedForm = removeFinalAmpersandIfPresent(serializedForm);
// Get the base URL
var urlString = window.location.protocol + '//' + window.location.host + window.location.pathname;
// Append the serialized form
urlString += "?" + serializedForm;
// Create a temporary element and store the URL in it
var tempElement = document.createElement("p");
tempElement.innerHTML = urlString;
// Append temporary element to the DOM so we can copy its contents
document.body.appendChild(tempElement);
// Copy to the clipboard
copyTextToClipboard(tempElement);
// Remove the temporary text area
tempElement.parentNode.removeChild(tempElement);
}
// Reloads the page and sets all options back to the defaults
function clearAndReload() {
if (confirm("Are you sure you want to set all options to default values?")) {
location.replace(window.location.pathname);
} else {
// Do nothing
}
}
// This is the alternative action to submitting the form when the user presses return in a text field
function handleSubmit() {
processChange();
return false;
}
</script>
<style>
body {
font-family: verdana;
font-size: 10pt;
}
table {
font-size: 10pt;
}
label {
vertical-align: middle;
}
input {
vertical-align: middle;
}
input[type=button] {
font-size: 8pt;
height:22px;
text-align: center;
padding: 0px;
}
input[type=text] {
padding: 2px 2px;
box-sizing: border-box;
}
input[type=number] {
width: 70px;
padding: 2px 2px;
box-sizing: border-box;
}
select {
padding: 2px 2px;
box-sizing: border-box;
vertical-align: middle;
}
li {
padding: 1px 0px;
}
label[data-disabled=true] {
color: #ccc;
}
label[data-disabled=false] {
color: #000;
}
ul {
list-style-type: none;
padding: 0px;
margin-block-end: 0;
}
</style>
<link rel="stylesheet" type="text/css" href="../css/oj9_option_builder.css">
</head>
<body onload="initialSetup()">
<form id="XdumpForm" name="XdumpForm" onsubmit="event.preventDefault(); return handleSubmit()">
<table border="0" cellspacing="0" cellpadding="4" style="width:1150px; table-layout:fixed">
<tr>
<td class="head1" colspan="2">
OpenJ9: Xdump Option Builder
</td>
</tr>
<tr>
<td style="vertical-align: top;" rowspan="2">
<b style="font-size: 12pt">Dump Events</b>
<hr>
<ul id="event_input">
<li>
<input type="checkbox" id="event_user" name="event" value="user" onchange="processChange(this)" data-hasfilter="false">
<label for="event_user">User signal i.e. SIGQUIT ("kill -3") / SIGBREAK</label>
</li>
<li>
<input type="checkbox" id="event_gpf" name="event" value="gpf" onchange="processChange(this)" data-hasfilter="false">
<label for="event_gpf">General Protection Fault (GPF) or unexpected SIGSEGV</label>
</li>
<li>
<input type="checkbox" id="event_abort" name="event" value="abort" onchange="processChange(this)" data-hasfilter="false">
<label for="event_abort">Process abort i.e. SIGABRT</label>
</li>
<li>
<input type="checkbox" id="event_traceassert" name="event" value="traceassert" onchange="processChange(this)" data-hasfilter="false">
<label for="event_traceassert">Internal JVM error (assertion failure)</label>
</li>
<li>
<input type="checkbox" id="event_corruptcache" name="event" value="corruptcache"onchange="processChange(this)" data-hasfilter="false">
<label for="event_corruptcache">Corrupt shared classes cache</label>
</li>
<li>
<input type="checkbox" id="event_excessivegc" name="event" value="excessivegc" onchange="processChange(this)" data-hasfilter="false">
<label for="event_excessivegc">Excessive GC activity</label>
</li>
<li>
<input type="checkbox" id="event_fullgc" name="event" value="fullgc" onchange="processChange(this)" data-hasfilter="false">
<label for="event_fullgc">Global GC</label>
</li>
<li>
<input type="checkbox" id="event_vmstart" name="event" value="vmstart" onchange="processChange(this)" data-hasfilter="false">
<label for="event_vmstart">VM startup</label>
</li>
<li>
<input type="checkbox" id="event_vmstop" name="event" value="vmstop" onchange="processChange(this)" data-hasfilter="true">
<label for="event_vmstop">VM shutdown. Exit code:</label>
<input type="number" id="event_vmstop_filter" name="vmstop_text" min="-9999" max="9999" value="" disabled onchange="processChange(this)" onBlur="processChange(this)">
</li>
<li>
<input type="checkbox" id="event_thrstart" name="event" value="thrstart" onchange="processChange(this)" data-hasfilter="false">
<label for="event_thrstart">Thread started</label>
</li>
<li>
<input type="checkbox" id="event_thrstop" name="event" value="thrstop" onchange="processChange(this)" data-hasfilter="false">
<label for="event_thrstop">Thread stopped</label>
</li>
<li>
<input type="checkbox" id="event_blocked" name="event" value="blocked" onchange="processChange(this)" data-hasfilter="false">
<label for="event_blocked">Thread blocked</label>
</li>
<li>
<input type="checkbox" id="event_slow" name="event" value="slow" onchange="processChange(this)" data-hasfilter="true">
<label for="event_slow">Thread slow/hung. Unresponsive threshold in ms:</label>
<input type="number" id="event_slow_filter" name="slow_ms" size="2" value = "50" min="1" max="9999" disabled onchange="processChange(this)" onBlur="processChange(this)">
</li>
<hr>
<li>
<input type="checkbox" id="event_allocation" name="event" value="allocation" onchange="processChange(this)" data-hasfilter="true">
<label for="event_allocation">Object allocated</label>
<br>
<table>
<tr>
<td>
<label data-disabled="true" for="event_allocation_filter_size_min">Minimum size:</label>
</td>
<td>
<input type="number" id="event_allocation_filter_size_min" name="event_allocation_filter_size_min" min="1" max="9999" value="256" disabled onchange="processChange(this)" onBlur="processChange(this)">
<select id="event_allocation_filter_units_min" name="event_allocation_filter_units_min" size="1" disabled onchange="processChange(this)">
<option value=""> bytes </option>
<option value="k" selected> kilobytes</option>
<option value="m"> megabytes </option>
</select>
</td>
</tr>
<tr>
<td>
<label data-disabled="true" for="event_allocation_filter_size_max">Maximum size:</label>
</td>
<td>
<input type="number" id="event_allocation_filter_size_max" name="event_allocation_filter_size_max" min="1" max="9999" value="512" disabled onchange="processChange(this)" onBlur="processChange(this)">
<select id="event_allocation_filter_units_max" name="event_allocation_filter_units_max" size="1" disabled onchange="processChange(this)">
<option value=""> bytes </option>
<option value="k" selected> kilobytes</option>
<option value="m"> megabytes </option>
</select>
</td>
</tr>
</table>
</li>
<hr>
<li>
<input type="checkbox" id="event_throw" name="event" value="throw" onchange="processChange(this)" data-hasfilter="true">
<label for="event_throw">Exception thrown by Java code</label>
</li>
<li>
<input type="checkbox" id="event_systhrow" name="event" value="systhrow" onchange="processChange(this)" data-hasfilter="true">
<label for="event_systhrow">Exception thrown by JVM internals</label>
</li>
<li>
<input type="checkbox" id="event_catch" name="event" value="catch" onchange="processChange(this)" data-hasfilter="true">
<label for="event_catch">Exception caught</label>
</li>
<li>
<input type="checkbox" id="event_uncaught" name="event" value="uncaught" onchange="processChange(this)" data-hasfilter="true">
<label for="event_uncaught">Exception uncaught</label>
<table>
<tr>
<td><label data-disabled="true" for="event_throwable_class">Exception class name:</label></td>
<td><input style="width: 400px" type="text" id="event_throwable_class" name="throwable_class" size="41" value="" disabled onchange="processChange(this)" onBlur="processChange(this)"></td>
</tr>
<tr>
<td><label data-disabled="true" for="event_throwable_method">Method name / offset:</label></td>
<td nowrap>
<input style="width: 325px" type="text" id="event_throwable_method" name="throwable_method" size="30" value="" disabled onchange="processChange(this)" onBlur="processChange(this)">
<input type="number" id="event_throwable_offset" name="range_first" min="0" max="999" value="0" size="4" disabled onchange="processChange(this)" onBlur="processChange(this)" onBlur="processChange(this)">
</td>
</tr>
<tr>
<td><label data-disabled="true" for="event_throwable_msg_filter">Exception message:</label></td>
<td><input style="width: 400px" type="text" id="event_throwable_msg_filter" name="throwable_message" size="41" value="" disabled onchange="processChange(this)" onBlur="processChange(this)"></td>
</tr>
</table>
</li>
<hr>
<li>
<input type="checkbox" id="event_load" name="event" value="load" onchange="processChange(this)" data-hasfilter="true">
<label for="event_load">Class loaded</label>
</li>
<li>
<input type="checkbox" id="event_unload" name="event" value="unload" onchange="processChange(this)" data-hasfilter="true">
<label for="event_unload">Class unloaded</label><br>
<label data-disabled="true" for="event_class_filter">Class name:</label> <input style="width: 470px" type="text" id="event_class_filter" name="class_text" size="57" value="" disabled onchange="processChange(this)" onBlur="processChange(this)">
</li>
</ul>
</td>
<td style="vertical-align: top;">
<b style="font-size: 12pt">Dump Agents</b>
<hr>
<ul id="agent_input">
<li>
<input type="checkbox" id="agent_stack" name="agent" value="stack" onchange="processChange(this)">
<label for="agent_stack">Write current Java&trade; thread stack to stderr</label>
</li>
<li>
<input type="checkbox" id="agent_console" name="agent" value="console" onchange="processChange(this)">
<label for="agent_console">Write all Java thread stacks to stderr</label>
</li>
<li>
<input type="checkbox" id="agent_system" name="agent" value="system" onchange="processChange(this)">
<label for="agent_system">Generate a system dump (core file / SYSTDUMP)</label>
</li>
<li>
<input type="checkbox" id="agent_java" name="agent" value="java" onchange="processChange(this)">
<label for="agent_java">Generate a Java dump (Java core)</label>
</li>
<li>
<input type="checkbox" id="agent_heap" name="agent" value="heap" onchange="processChange(this)">
<label for="agent_heap">Generate a PHD heap dump (system dump is usually preferred)</label>
</li>
<li>
<input type="checkbox" id="agent_snap" name="agent" value="snap" onchange="processChange(this)">
<label for="agent_snap">Generate a Snap dump (contents of the JVM's trace buffers)</label>
</li>
<li>
<input type="checkbox" id="agent_jit" name="agent" value="jit" onchange="processChange(this)">
<label for="agent_jit">Generate a JIT dump</label>
</li>
<li>
<input type="checkbox" id="agent_ceedump" name="agent" value="ceedump" onchange="processChange(this)">
<label for="agent_ceedump">Generate an LE CEEDUMP dump (z/OS only)</label>
</li>
<li id="agent_exit_li">
<input type="checkbox" id="agent_exit" name="agent" value="exit" onchange="processChange(this)">
<label for="agent_exit">Shutdown the JVM</label>
</li>
<li>
<input type="checkbox" id="agent_tool" name="agent" value="tool" onchange="processChange(this)" onmousedown="registerToolExecMouseDown()">
<label for="agent_tool" onmousedown="registerToolExecMouseDown()">Run a shell command:</label><br>
<input style="width: 558px" type="text" id="exec" name="exec" size="71" value="" disabled onchange="processChange(this)" onblur="processChange(this)">
<div style="padding: 4px 0px;">
<input type="button" data-target="exec" data-token="%Y" id="exec_button_year4" disabled style="width:55px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Year (4)" title="Year (4 digits) e.g. 2017">
<input type="button" data-target="exec" data-token="%y" id="exec_button_year2" disabled style="width:55px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Year (2)" title="Year (2 digits) e.g. 17">
<input type="button" data-target="exec" data-token="%m" id="exec_button_month" disabled style="width:48px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Month" title="Month (2 digits) e.g. 08">
<input type="button" data-target="exec" data-token="%d" id="exec_button_day" disabled style="width:34px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Day" title="Day of month (2 digits) e.g. 26">
<input type="button" data-target="exec" data-token="%H" id="exec_button_hour" disabled style="width:38px;" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Hour" title="Hour of day (2 digits) e.g. 05">
<input type="button" data-target="exec" data-token="%M" id="exec_button_minute" disabled style="width:34px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Min" title="Minute of hour (2 digits) e.g. 47">
<input type="button" data-target="exec" data-token="%S" id="exec_button_second" disabled style="width:34px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Sec" title="Second of minute (2 digits) e.g. 35">
<input type="button" data-target="exec" data-token="%pid" id="exec_button_pid" disabled style="width:33px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="PID" title="JVM Process ID e.g. 27491">
<input type="button" data-target="exec" data-token="%job" id="exec_button_jobname" disabled style="width:65px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Job Name" title="Job Name (z/OS only)">
&nbsp;
<input type="checkbox" id="tool_async" name="tool_async" value="ASYNC" title="If checked, the JVM will continue without waiting for the command to complete" disabled onchange="processChange(this)">
<label for="tool_async" data-disabled="true" title="Run asynchronously. If checked, the JVM will continue without waiting for the command to complete">Asyncronous</label>
</div>
<div>
<input type="button" data-target="exec" data-token="%uid" id="exec_button_uname" disabled style="width:50px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Uname" title="User name e.g. jbloggs">
<input type="button" data-target="exec" data-token="%seq" id="exec_button_dumpcounter" disabled style="width:45px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Count" title="Dump Counter e.g. 0004">
<input type="button" data-target="exec" data-token="%tick" id="exec_button_mscounter" disabled style="width:43px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Ticks" title="Millisecond counter e.g. 638349">
<input type="button" data-target="exec" data-token="%last" id="exec_button_lastdump" disabled style="width:70px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Last Dump" title="Last dump name">
<input type="button" data-target="exec" data-token="%home" id="exec_button_javahome" disabled style="width:70px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Java Home" title="Java Home e.g. /home/jbloggs/java">
<input type="button" data-target="exec" data-token="%asid" id="exec_button_asid" disabled style="width:45px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="ASID" title="Address Space ID (z/OS only)">
<input type="button" data-target="exec" data-token="&DS" id="exec_button_ds" disabled style="width:30px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="DS" title="Dump Section (64-bit z/OS only)">
<input type="button" data-target="exec" data-token="%jobid" id="exec_button_jobid" disabled style="width:48px" onclick="processChange(this)"
onmousedown="registerToolExecMouseDown()" value="Job ID" title="Job ID (z/OS only)">
&nbsp;
<label for="tool_wait" data-disabled="true" title="Time to wait after executing the command, in milliseconds">Wait: </label>
<input type="number" id="tool_wait" name="tool_wait" style="width:70px" min="0" value="0" disabled title="Time to wait after executing the command, in milliseconds" onchange="processChange(this)">
</div>
</li>
<hr>
</ul>
</td>
</tr>
<tr>
<td>
<b style="font-size: 12pt">Dump Options</b>
<hr>
<ul id="options_input">
<div id="request_input">
<li>
<input type="checkbox" id="request_exclusive" name="request" value="exclusive" onchange="processChange(this)">
<label for="request_exclusive">Obtain exclusive JVM access before dumping</label>
</li>
<li>
<input type="checkbox" id="request_compact" name="request" value="compact" onchange="processChange(this)">
<label for="request_compact">Run global GC before dumping (i.e. remove garbage objects)</label>
</li>
<li>
<input type="checkbox" id="request_prepwalk" name="request" value="prepwalk" onchange="processChange(this)">
<label for="request_prepwalk">Ensure heap is walkable before dumping</label>
</li>
<li>
<input type="checkbox" id="request_serial" name="request" value="serial" onchange="processChange(this)">
<label for="request_serial">Suspend other dumps while dumping</label>
</li>
<li>
<input type="checkbox" id="request_preempt" name="request" value="preempt" onchange="processChange(this)">
<label for="request_preempt">Enable native thread stacks in javacore</label>
</li>
</div>
<hr>
<li id="range_li">
<label for="range_first">First / last events:</label>
<input type="number" id="range_first" name="range_first" min="1" max="9999" value="1" size="4" onchange="processChange(this)" onBlur="processChange(this)">
&nbsp;
<input type="number" id="range_last" name="range_last" min="0" max="9999" value="0" size="4" onchange="processChange(this)" onBlur="processChange(this)">
<label for="range_last">(0 = no limit)</label>
</li>
<hr>
<li>
<label for="priority">Dump priority:</label>
<input type="number" id="priority" name="priority" min="0" max="999" size="4" onchange="processChange(this)" onBlur="processChange(this)">
<label for="priority">(0 [lowest] - 999 [highest])</label>
</li>
<hr>
<li>
<label for="file_text" data-disabled="true">Dump file pattern (all dumps except SYSTDUMPs and CEEDUMPs):</label>
<input style="width: 558px" type="text" id="file_text" name="file_text" size="71" value="" disabled onchange="processChange(this)" onblur="registerTokenTarget(this)">
</li>
<li>
<label for="dsn_text" data-disabled="true">Data set pattern (SYSTDUMPs only):</label>
<input style="width: 558px" type="text" id="dsn_text" name="dsn_text" size="71" value="" disabled onchange="processChange(this)" onblur="registerTokenTarget(this)">
</li>
<li>
<div style="padding: 4px 0px;">
<input type="button" data-token="%Y" id="file_button_year4" disabled style="width:55px" onclick="processChange(this)"
value="Year (4)" title="Year (4 digits) e.g. 2017">
<input type="button" data-token="%y" id="file_button_year2" disabled style="width:55px" onclick="processChange(this)"
value="Year (2)" title="Year (2 digits) e.g. 17">
<input type="button" data-token="%m" id="file_button_month" disabled style="width:48px" onclick="processChange(this)"
value="Month" title="Month (2 digits) e.g. 08">
<input type="button" data-token="%d" id="file_button_day" disabled style="width:34px" onclick="processChange(this)"
value="Day" title="Day of month (2 digits) e.g. 26">
<input type="button" data-token="%H" id="file_button_hour" disabled style="width:38px" onclick="processChange(this)"
value="Hour" title="Hour of day (2 digits) e.g. 05">
<input type="button" data-token="%M" id="file_button_minute" disabled style="width:34px" onclick="processChange(this)"
value="Min" title="Minute of hour (2 digits) e.g. 47">
<input type="button" data-token="%S" id="file_button_second" disabled style="width:34px" onclick="processChange(this)"
value="Sec" title="Second of minute (2 digits) e.g. 35">
<input type="button" data-token="%pid" id="file_button_pid" disabled style="width:33px" onclick="processChange(this)"
value="PID" title="JVM Process ID e.g. 27491">
<input type="button" data-token="%job" id="file_button_jobname" disabled style="width:65px" onclick="processChange(this)"
value="Job Name" title="Job Name (z/OS only)">
</div>
<div>
<input type="button" data-token="%uid" id="file_button_uname" disabled style="width:50px" onclick="processChange(this)"
value="Uname" title="User name e.g. jbloggs">
<input type="button" data-token="%seq" id="file_button_dumpcounter" disabled style="width:45px" onclick="processChange(this)"
value="Count" title="Dump Counter e.g. 0004">
<input type="button" data-token="%tick" id="file_button_mscounter" disabled style="width:43px" onclick="processChange(this)"
value="Ticks" title="Millisecond counter e.g. 638349">
<input type="button" data-token="%last" id="file_button_lastdump" disabled style="width:70px" onclick="processChange(this)"
value="Last Dump" title="Last dump name">
<input type="button" data-token="%home" id="file_button_javahome" disabled style="width:70px" onclick="processChange(this)"
value="Java Home" title="Java Home e.g. /home/jbloggs/java">
<input type="button" data-token="%asid" id="file_button_asid" disabled style="width:45px" onclick="processChange(this)"
value="ASID" title="Address Space ID (z/OS only)">
<input type="button" data-token="&DS" id="file_button_ds" disabled style="width:30px" onclick="processChange(this)"
value="DS" title="Dump Section (64-bit z/OS only)">
<input type="button" data-token="%jobid" id="file_button_jobid" disabled style="width:48px" onclick="processChange(this)"
value="Job ID" title="Job ID (z/OS only)">
</div>
</li>
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<hr>
<b><p id="result" style="font-size: 14pt; font-family:courier;">&nbsp;</p></b>
<hr>
<p>
<input type="checkbox" id="wrap_in_quotes" name="wrap_in_quotes" value="wrap_in_quotes" onchange="processChange(this)" checked>
<label for="wrap_in_quotes">Wrap in quotes (for use in a shell)</label>
</p>
<p>
<button type="button" id="button_copy_to_clipboard" style="font-size: 12pt; height:30px;width:200px" onclick="copyTextToClipboard(document.getElementById('result'))" title="Copy this -Xdump option to the clipboard">Copy option</button>
<button type="button" id="button_copy_link_to_clipboard" style="font-size: 12pt; height:30px;width:200px" onclick="copyLinkToClipboard()" title="Copy a link to this -Xdump option to the clipboard">Copy link</button>
<button type="button" id="button_reset" style="font-size: 12pt; height:30px;width:200px" onclick="location.reload()"title="Reset all options to the values that were set when this page was originally loaded">Reset</button>
<button type="button" id="button_clear" style="font-size: 12pt; height:30px;width:200px" onclick="clearAndReload()" title="Clear all options and set default values">Clear</button>
</p>
<p id="errors" style="font-size: 12pt; font-family:courier; color:red;">&nbsp;</p></b>
</td>
</tr>
</table>
</form>
</body>
</html>