8340133: Add concise usage message to the java executable

Reviewed-by: jpai, alanb, ihse, rriggs
This commit is contained in:
Jan Lahoda 2024-12-02 11:21:13 +00:00
parent 0b0f83c01e
commit c7be41ee0c
3 changed files with 97 additions and 54 deletions

View file

@ -589,6 +589,15 @@ public final class LauncherHelper {
} }
} }
/**
* Prints the short usage text to the desired output stream.
*/
static void printConciseUsageMessage(boolean printToStderr) {
initOutput(printToStderr);
ostream.println(getLocalizedMessage("java.launcher.opt.concise.header",
File.pathSeparator));
}
static void initOutput(boolean printToStderr) { static void initOutput(boolean printToStderr) {
ostream = (printToStderr) ? System.err : System.out; ostream = (printToStderr) ? System.err : System.out;
} }

View file

@ -26,14 +26,14 @@
# Translators please note do not translate the options themselves # Translators please note do not translate the options themselves
java.launcher.opt.header = Usage: {0} [options] <mainclass> [args...]\n\ java.launcher.opt.header = Usage: {0} [options] <mainclass> [args...]\n\
\ (to execute a class)\n\ \ (to execute a class)\n\
\ or {0} [options] -jar <jarfile> [args...]\n\ \ or {0} [options] -jar <jarfile>.jar [args...]\n\
\ (to execute a jar file)\n\ \ (to execute a jar file)\n\
\ or {0} [options] -m <module>[/<mainclass>] [args...]\n\ \ or {0} [options] -m <module>[/<mainclass>] [args...]\n\
\ {0} [options] --module <module>[/<mainclass>] [args...]\n\ \ {0} [options] --module <module>[/<mainclass>] [args...]\n\
\ (to execute the main class in a module)\n\ \ (to execute the main class in a module)\n\
\ or {0} [options] <sourcefile> [args]\n\ \ or {0} [options] <sourcefile>.java [args]\n\
\ (to execute a source-file program)\n\n\ \ (to execute a source-file program)\n\n\
\ Arguments following the main class, source file, -jar <jarfile>,\n\ \ Arguments following the main class, source file, -jar <jarfile>.jar,\n\
\ -m or --module <module>/<mainclass> are passed as the arguments to\n\ \ -m or --module <module>/<mainclass> are passed as the arguments to\n\
\ main class.\n\n\ \ main class.\n\n\
\ where options include:\n\n \ where options include:\n\n
@ -46,15 +46,15 @@ java.launcher.opt.footer = \
\ -cp <class search path of directories and zip/jar files>\n\ \ -cp <class search path of directories and zip/jar files>\n\
\ -classpath <class search path of directories and zip/jar files>\n\ \ -classpath <class search path of directories and zip/jar files>\n\
\ --class-path <class search path of directories and zip/jar files>\n\ \ --class-path <class search path of directories and zip/jar files>\n\
\ A {0} separated list of directories, JAR archives,\n\ \ A "{0}"-separated list of directories, JAR archives,\n\
\ and ZIP archives to search for class files.\n\ \ and ZIP archives to search for class files.\n\
\ -p <module path>\n\ \ -p <module path>\n\
\ --module-path <module path>...\n\ \ --module-path <module path>...\n\
\ A {0} separated list of elements, each element is a file path\n\ \ A "{0}"-separated list of elements, each element is a file path\n\
\ to a module or a directory containing modules. Each module is either\n\ \ to a module or a directory containing modules. Each module is either\n\
\ a modular JAR or an exploded-module directory.\n\ \ a modular JAR or an exploded-module directory.\n\
\ --upgrade-module-path <module path>...\n\ \ --upgrade-module-path <module path>...\n\
\ A {0} separated list of elements, each element is a file path\n\ \ A "{0}"-separated list of elements, each element is a file path\n\
\ to a module or a directory containing modules to replace\n\ \ to a module or a directory containing modules to replace\n\
\ upgradeable modules in the runtime image. Each module is either\n\ \ upgradeable modules in the runtime image. Each module is either\n\
\ a modular JAR or an exploded-module directory.\n\ \ a modular JAR or an exploded-module directory.\n\
@ -232,6 +232,23 @@ The following options are macOS specific:\n\
\ -Xdock:icon=<path to icon file>\n\ \ -Xdock:icon=<path to icon file>\n\
\ override default icon displayed in dock\n\n \ override default icon displayed in dock\n\n
# Translators please note do not translate the options themselves
java.launcher.opt.concise.header = Usage: java [java options...] <application> [application arguments...]\n\n\
\Where <application> is one of:\n\
\ <mainclass> to execute the main method of a compiled main class\n\
\ -jar <jarfile>.jar to execute the main class of a JAR archive\n\
\ -m <module>[/<mainclass>] to execute the main class of a module\n\
\ <sourcefile>.java to compile and execute a source-file program\n\n\
\Where key java options include:\n\
\ --class-path <class path>\n\
\ where <class path> is a list of directories and JAR archives to search for class files, separated by "{0}"\n\
\ --module-path <module path>\n\
\ where <module path> is a list of directories and JAR archives to search for modules, separated by "{0}"\n\
\ -version\n\
\ to print product version to the error stream and exit\n\n\
\For additional help on usage: java --help\n\
\For an interactive Java environment: jshell
java.launcher.bad.option=\ java.launcher.bad.option=\
\n\ \n\
Unrecognized showSettings option: {0}\n\ Unrecognized showSettings option: {0}\n\

View file

@ -63,11 +63,17 @@
#define USE_STDERR JNI_TRUE /* we usually print to stderr */ #define USE_STDERR JNI_TRUE /* we usually print to stderr */
#define USE_STDOUT JNI_FALSE #define USE_STDOUT JNI_FALSE
enum HelpKind {
HELP_NONE,
HELP_CONCISE,
HELP_FULL,
HELP_EXTRA
};
static jboolean printVersion = JNI_FALSE; /* print and exit */ static jboolean printVersion = JNI_FALSE; /* print and exit */
static jboolean showVersion = JNI_FALSE; /* print but continue */ static jboolean showVersion = JNI_FALSE; /* print but continue */
static jboolean printUsage = JNI_FALSE; /* print and exit*/ static enum HelpKind printUsageKind = HELP_NONE; /* if not NONE, print specified usage and exit*/
static jboolean printTo = USE_STDERR; /* where to print version/usage */ static jboolean printTo = USE_STDERR; /* where to print version/usage */
static jboolean printXUsage = JNI_FALSE; /* print and exit*/
static jboolean dryRun = JNI_FALSE; /* initialize VM and exit */ static jboolean dryRun = JNI_FALSE; /* initialize VM and exit */
static char *showSettings = NULL; /* print but continue */ static char *showSettings = NULL; /* print but continue */
static jboolean showResolvedModules = JNI_FALSE; static jboolean showResolvedModules = JNI_FALSE;
@ -120,7 +126,7 @@ static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc,
static jboolean AddApplicationOptions(int cpathc, const char **cpathv); static jboolean AddApplicationOptions(int cpathc, const char **cpathv);
static void PrintJavaVersion(JNIEnv *env); static void PrintJavaVersion(JNIEnv *env);
static void PrintUsage(JNIEnv* env, jboolean doXUsage); static void PrintUsage(JNIEnv* env, enum HelpKind printUsageKind);
static void ShowSettings(JNIEnv* env, char *optString); static void ShowSettings(JNIEnv* env, char *optString);
static void ShowResolvedModules(JNIEnv* env); static void ShowResolvedModules(JNIEnv* env);
static void ListModules(JNIEnv* env); static void ListModules(JNIEnv* env);
@ -179,7 +185,7 @@ static jboolean IsWildCardEnabled();
do { \ do { \
if (!AC_ok) { \ if (!AC_ok) { \
JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \ JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \
printUsage = JNI_FALSE; \ printUsageKind = HELP_NONE; \
*pret = 1; \ *pret = 1; \
return JNI_FALSE; \ return JNI_FALSE; \
} \ } \
@ -189,7 +195,7 @@ static jboolean IsWildCardEnabled();
do { \ do { \
if (AC_arg_count < 1) { \ if (AC_arg_count < 1) { \
JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \ JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \
printUsage = JNI_TRUE; \ printUsageKind = HELP_FULL; \
*pret = 1; \ *pret = 1; \
return JNI_TRUE; \ return JNI_TRUE; \
} \ } \
@ -537,8 +543,8 @@ JavaMain(void* _args)
} }
/* If the user specified neither a class name nor a JAR file */ /* If the user specified neither a class name nor a JAR file */
if (printXUsage || printUsage || what == 0 || mode == LM_UNKNOWN) { if (printUsageKind != HELP_NONE) {
PrintUsage(env, printXUsage); PrintUsage(env, printUsageKind);
CHECK_EXCEPTION_LEAVE(1); CHECK_EXCEPTION_LEAVE(1);
LEAVE(); LEAVE();
} }
@ -1235,10 +1241,10 @@ ParseArguments(int *pargc, char ***pargv,
} else if (JLI_StrCmp(arg, "-help") == 0 || } else if (JLI_StrCmp(arg, "-help") == 0 ||
JLI_StrCmp(arg, "-h") == 0 || JLI_StrCmp(arg, "-h") == 0 ||
JLI_StrCmp(arg, "-?") == 0) { JLI_StrCmp(arg, "-?") == 0) {
printUsage = JNI_TRUE; printUsageKind = HELP_FULL;
return JNI_TRUE; return JNI_TRUE;
} else if (JLI_StrCmp(arg, "--help") == 0) { } else if (JLI_StrCmp(arg, "--help") == 0) {
printUsage = JNI_TRUE; printUsageKind = HELP_FULL;
printTo = USE_STDOUT; printTo = USE_STDOUT;
return JNI_TRUE; return JNI_TRUE;
} else if (JLI_StrCmp(arg, "-version") == 0) { } else if (JLI_StrCmp(arg, "-version") == 0) {
@ -1256,10 +1262,10 @@ ParseArguments(int *pargc, char ***pargv,
} else if (JLI_StrCmp(arg, "--dry-run") == 0) { } else if (JLI_StrCmp(arg, "--dry-run") == 0) {
dryRun = JNI_TRUE; dryRun = JNI_TRUE;
} else if (JLI_StrCmp(arg, "-X") == 0) { } else if (JLI_StrCmp(arg, "-X") == 0) {
printXUsage = JNI_TRUE; printUsageKind = HELP_EXTRA;
return JNI_TRUE; return JNI_TRUE;
} else if (JLI_StrCmp(arg, "--help-extra") == 0) { } else if (JLI_StrCmp(arg, "--help-extra") == 0) {
printXUsage = JNI_TRUE; printUsageKind = HELP_EXTRA;
printTo = USE_STDOUT; printTo = USE_STDOUT;
return JNI_TRUE; return JNI_TRUE;
/* /*
@ -1350,6 +1356,7 @@ ParseArguments(int *pargc, char ***pargv,
/* LM_UNKNOWN okay for options that exit */ /* LM_UNKNOWN okay for options that exit */
if (!listModules && !describeModule && !validateModules && !dumpSharedSpaces) { if (!listModules && !describeModule && !validateModules && !dumpSharedSpaces) {
*pret = 1; *pret = 1;
printUsageKind = HELP_CONCISE;
} }
} else if (mode == LM_UNKNOWN) { } else if (mode == LM_UNKNOWN) {
if (!_have_classpath) { if (!_have_classpath) {
@ -1919,58 +1926,68 @@ DescribeModule(JNIEnv *env, char *optString)
* Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java * Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java
*/ */
static void static void
PrintUsage(JNIEnv* env, jboolean doXUsage) PrintUsage(JNIEnv* env, enum HelpKind printUsageKind)
{ {
jmethodID initHelp, vmSelect, vmSynonym, printHelp, printXUsageMessage; jmethodID initHelp, vmSelect, vmSynonym;
jmethodID printHelp, printConciseUsageMessage, printXUsageMessage;
jstring jprogname, vm1, vm2; jstring jprogname, vm1, vm2;
int i; int i;
jclass cls = GetLauncherHelperClass(env); jclass cls = GetLauncherHelperClass(env);
NULL_CHECK(cls); NULL_CHECK(cls);
if (doXUsage) { switch (printUsageKind) {
NULL_CHECK(printXUsageMessage = (*env)->GetStaticMethodID(env, cls, case HELP_NONE: break;
"printXUsageMessage", "(Z)V")); case HELP_CONCISE:
(*env)->CallStaticVoidMethod(env, cls, printXUsageMessage, printTo); NULL_CHECK(printConciseUsageMessage = (*env)->GetStaticMethodID(env, cls,
} else { "printConciseUsageMessage", "(Z)V"));
NULL_CHECK(initHelp = (*env)->GetStaticMethodID(env, cls, (*env)->CallStaticVoidMethod(env, cls, printConciseUsageMessage, printTo);
"initHelpMessage", "(Ljava/lang/String;)V")); break;
case HELP_EXTRA:
NULL_CHECK(printXUsageMessage = (*env)->GetStaticMethodID(env, cls,
"printXUsageMessage", "(Z)V"));
(*env)->CallStaticVoidMethod(env, cls, printXUsageMessage, printTo);
break;
case HELP_FULL:
NULL_CHECK(initHelp = (*env)->GetStaticMethodID(env, cls,
"initHelpMessage", "(Ljava/lang/String;)V"));
NULL_CHECK(vmSelect = (*env)->GetStaticMethodID(env, cls, "appendVmSelectMessage", NULL_CHECK(vmSelect = (*env)->GetStaticMethodID(env, cls, "appendVmSelectMessage",
"(Ljava/lang/String;Ljava/lang/String;)V")); "(Ljava/lang/String;Ljava/lang/String;)V"));
NULL_CHECK(vmSynonym = (*env)->GetStaticMethodID(env, cls, NULL_CHECK(vmSynonym = (*env)->GetStaticMethodID(env, cls,
"appendVmSynonymMessage", "appendVmSynonymMessage",
"(Ljava/lang/String;Ljava/lang/String;)V")); "(Ljava/lang/String;Ljava/lang/String;)V"));
NULL_CHECK(printHelp = (*env)->GetStaticMethodID(env, cls, NULL_CHECK(printHelp = (*env)->GetStaticMethodID(env, cls,
"printHelpMessage", "(Z)V")); "printHelpMessage", "(Z)V"));
NULL_CHECK(jprogname = (*env)->NewStringUTF(env, _program_name)); NULL_CHECK(jprogname = (*env)->NewStringUTF(env, _program_name));
/* Initialize the usage message with the usual preamble */ /* Initialize the usage message with the usual preamble */
(*env)->CallStaticVoidMethod(env, cls, initHelp, jprogname); (*env)->CallStaticVoidMethod(env, cls, initHelp, jprogname);
CHECK_EXCEPTION_RETURN(); CHECK_EXCEPTION_RETURN();
/* Assemble the other variant part of the usage */ /* Assemble the other variant part of the usage */
for (i=1; i<knownVMsCount; i++) { for (i=1; i<knownVMsCount; i++) {
if (knownVMs[i].flag == VM_KNOWN) { if (knownVMs[i].flag == VM_KNOWN) {
NULL_CHECK(vm1 = (*env)->NewStringUTF(env, knownVMs[i].name)); NULL_CHECK(vm1 = (*env)->NewStringUTF(env, knownVMs[i].name));
NULL_CHECK(vm2 = (*env)->NewStringUTF(env, knownVMs[i].name+1)); NULL_CHECK(vm2 = (*env)->NewStringUTF(env, knownVMs[i].name+1));
(*env)->CallStaticVoidMethod(env, cls, vmSelect, vm1, vm2); (*env)->CallStaticVoidMethod(env, cls, vmSelect, vm1, vm2);
CHECK_EXCEPTION_RETURN(); CHECK_EXCEPTION_RETURN();
}
} }
} for (i=1; i<knownVMsCount; i++) {
for (i=1; i<knownVMsCount; i++) { if (knownVMs[i].flag == VM_ALIASED_TO) {
if (knownVMs[i].flag == VM_ALIASED_TO) { NULL_CHECK(vm1 = (*env)->NewStringUTF(env, knownVMs[i].name));
NULL_CHECK(vm1 = (*env)->NewStringUTF(env, knownVMs[i].name)); NULL_CHECK(vm2 = (*env)->NewStringUTF(env, knownVMs[i].alias+1));
NULL_CHECK(vm2 = (*env)->NewStringUTF(env, knownVMs[i].alias+1)); (*env)->CallStaticVoidMethod(env, cls, vmSynonym, vm1, vm2);
(*env)->CallStaticVoidMethod(env, cls, vmSynonym, vm1, vm2); CHECK_EXCEPTION_RETURN();
CHECK_EXCEPTION_RETURN(); }
} }
}
/* Complete the usage message and print to stderr*/ /* Complete the usage message and print to stderr*/
(*env)->CallStaticVoidMethod(env, cls, printHelp, printTo); (*env)->CallStaticVoidMethod(env, cls, printHelp, printTo);
break;
} }
return; return;
} }