https://mail.openjdk.java.net/pipermail/serviceability-dev/2019-June/028376.html
Also just an observation that there is some room for option processing
refactoring.
All the jhsdb sub-commands do execute similar loops like this:
while((s = sg.next(null, longOpts)) != null) {
. . .
}
It can be moved into a separate method instead.
The longOpts can passed in arguments.
It can be something like this:
private ArrayList<String> processOptions(final String[] oldArgs,
final String[] longOpts,
boolean allowEmpty) {
SAGetopt sg = new SAGetopt(oldArgs);
ArrayList<String> newArgs = new ArrayList();
String pid = null;
String exe = null;
String core = null;
String s = null;
String dumpfile = null;
String remote = NO_REMOTE;
boolean requestHeapdump = false;
while((s = sg.next(null, longOpts)) != null) {
if (s.equals("exe")) {
exe = sg.getOptarg();
continue;
}
if (s.equals("core")) {
core = sg.getOptarg();
continue;
}
if (s.equals("pid")) {
pid = sg.getOptarg();
continue;
}
if (s.equals("remote")) {
remote = sg.getOptarg();
continue;
}
if (s.equals("mixed")) {
newArgs.add("-m");
continue;
}
if (s.equals("locks")) {
newArgs.add("-l");
continue;
}
if (s.equals("heap")) {
newArgs.add("-heap");
continue;
}
if (s.equals("binaryheap")) {
requestHeapdump = true;
continue;
}
if (s.equals("dumpfile")) {
dumpfile = sg.getOptarg();
continue;
}
if (s.equals("histo")) {
newArgs.add("-histo");
continue;
}
if (s.equals("clstats")) {
newArgs.add("-clstats");
continue;
}
if (s.equals("finalizerinfo")) {
newArgs.add("-finalizerinfo");
continue;
}
if (s.equals("flags")) {
newArgs.add("-flags");
continue;
}
if (s.equals("sysprops")) {
newArgs.add("-sysprops");
continue;
}
if (s.equals("serverid")) {
String serverid = sg.getOptarg();
if (serverid != null) {
newArgs.add(serverid);
}
continue;
}
}
if (!requestHeapdump && (dumpfile != null)) {
throw new IllegalArgumentException("Unexpected argument
dumpfile");
}
if (requestHeapdump) {
if (dumpfile == null) {
newArgs.add("-heap:format=b");
} else {
newArgs.add("-heap:format=b,file=" + dumpfile);
}
}
buildAttachArgs(newArgs, pid, exe, core, remote, allowEmpty);
return newArgs;
}
private static void runCLHSDB(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid="};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
true);
CLHSDB.main(newArgs.toArray(new String[newArgs.size()]));
}
private static void runHSDB(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid="};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
true);
HSDB.main(newArgs.toArray(new String[newArgs.size()]));
}
private static void runJSTACK(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid=", "remote=",
"mixed", "locks"};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
false);
JStack jstack = new JStack(false, false);
jstack.runWithArgs(newArgs.toArray(new String[newArgs.size()]));
}
private static void runJMAP(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid=", "remote=",
"heap", "binaryheap", "dumpfile=", "histo", "clstats",
"finalizerinfo"};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
false);
JMap.main(newArgs.toArray(new String[newArgs.size()]));
}
Also just an observation that there is some room for option processing
refactoring.
All the jhsdb sub-commands do execute similar loops like this:
while((s = sg.next(null, longOpts)) != null) {
. . .
}
It can be moved into a separate method instead.
The longOpts can passed in arguments.
It can be something like this:
private ArrayList<String> processOptions(final String[] oldArgs,
final String[] longOpts,
boolean allowEmpty) {
SAGetopt sg = new SAGetopt(oldArgs);
ArrayList<String> newArgs = new ArrayList();
String pid = null;
String exe = null;
String core = null;
String s = null;
String dumpfile = null;
String remote = NO_REMOTE;
boolean requestHeapdump = false;
while((s = sg.next(null, longOpts)) != null) {
if (s.equals("exe")) {
exe = sg.getOptarg();
continue;
}
if (s.equals("core")) {
core = sg.getOptarg();
continue;
}
if (s.equals("pid")) {
pid = sg.getOptarg();
continue;
}
if (s.equals("remote")) {
remote = sg.getOptarg();
continue;
}
if (s.equals("mixed")) {
newArgs.add("-m");
continue;
}
if (s.equals("locks")) {
newArgs.add("-l");
continue;
}
if (s.equals("heap")) {
newArgs.add("-heap");
continue;
}
if (s.equals("binaryheap")) {
requestHeapdump = true;
continue;
}
if (s.equals("dumpfile")) {
dumpfile = sg.getOptarg();
continue;
}
if (s.equals("histo")) {
newArgs.add("-histo");
continue;
}
if (s.equals("clstats")) {
newArgs.add("-clstats");
continue;
}
if (s.equals("finalizerinfo")) {
newArgs.add("-finalizerinfo");
continue;
}
if (s.equals("flags")) {
newArgs.add("-flags");
continue;
}
if (s.equals("sysprops")) {
newArgs.add("-sysprops");
continue;
}
if (s.equals("serverid")) {
String serverid = sg.getOptarg();
if (serverid != null) {
newArgs.add(serverid);
}
continue;
}
}
if (!requestHeapdump && (dumpfile != null)) {
throw new IllegalArgumentException("Unexpected argument
dumpfile");
}
if (requestHeapdump) {
if (dumpfile == null) {
newArgs.add("-heap:format=b");
} else {
newArgs.add("-heap:format=b,file=" + dumpfile);
}
}
buildAttachArgs(newArgs, pid, exe, core, remote, allowEmpty);
return newArgs;
}
private static void runCLHSDB(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid="};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
true);
CLHSDB.main(newArgs.toArray(new String[newArgs.size()]));
}
private static void runHSDB(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid="};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
true);
HSDB.main(newArgs.toArray(new String[newArgs.size()]));
}
private static void runJSTACK(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid=", "remote=",
"mixed", "locks"};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
false);
JStack jstack = new JStack(false, false);
jstack.runWithArgs(newArgs.toArray(new String[newArgs.size()]));
}
private static void runJMAP(String[] oldArgs) {
String[] longOpts = {"exe=", "core=", "pid=", "remote=",
"heap", "binaryheap", "dumpfile=", "histo", "clstats",
"finalizerinfo"};
ArrayList<String> newArgs = processOptions(oldArgs, longOpts,
false);
JMap.main(newArgs.toArray(new String[newArgs.size()]));
}