JDK-5030265 : Launcher misinterprets manifest Main-Class attribute
  • Type: Bug
  • Component: tools
  • Sub-Component: launcher
  • Affected Version: 5.0
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2004-04-12
  • Updated: 2016-12-05
  • Resolved: 2004-04-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 b49Fixed
Related Reports
Relates :  
Description

Name: nl37777			Date: 04/12/2004

The jar file manifest specification 
http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#JAR%20Manifest 
specifies UTF-8 as the encoding of the values of manifest attributes. 
However, the launcher src/share/bin/java.c interprets the string read 
from the Main-Class attribute of a jarfile manifest in the platform 
encoding. This means that applications with non-ASCII characters in the 
main class name generally cannot be launched.
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-beta2 FIXED IN: tiger-beta2 INTEGRATED IN: tiger-b49 tiger-beta2
14-06-2004

EVALUATION Name: nl37777 Date: 04/12/2004 Use suggested fix. ====================================================================== ###@###.### 2004-04-21 Actualy reverted to earlier code. See suggested fix. Note that the original suggested fix may be used in the future to restore the minor optimization disabled. >> From: Martin Buchholz <###@###.###> ... >>Transmission of ASCII environment variables will always be safe, and >>checking for ASCII-ness is very cheap compared to the overhead of >>starting up Java. (I won't even mention that you can test a region >>for ASCII-ness by and-ing with 0x80808080 if you're trying to save >>a few cycles). So in a future release we might be able to optimize >>away the use of Java to get the main-class, if there was a significant >>performance difference, which is only likely if we can save a >>whole Java startup.
11-06-2004

SUGGESTED FIX Name: nl37777 Date: 04/12/2004 *************** *** 93,98 **** --- 93,99 ---- char **pclassname, int *pret); static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn); + static jstring NewUTF8String(JNIEnv *env, char *s); static jstring NewPlatformString(JNIEnv *env, char *s); static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); static jclass LoadClass(JNIEnv *env, char *name); *************** *** 332,338 **** messageDest = JNI_TRUE; goto leave; } ! mainClassName = NewPlatformString(env, main_class); classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); if (classname == NULL) { ReportExceptionDescription(env); --- 333,339 ---- messageDest = JNI_TRUE; goto leave; } ! mainClassName = NewUTF8String(env, main_class); classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); if (classname == NULL) { ReportExceptionDescription(env); *************** *** 1021,1026 **** --- 1022,1060 ---- return p; } + /* + * Returns a new Java string object for the specified UTF-8 string. + */ + static jstring + NewUTF8String(JNIEnv *env, char *s) + { + int len = (int)strlen(s); + jclass cls; + jmethodID mid; + jbyteArray ary; + jobject utf8; + + if (s == NULL) + return 0; + NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); + NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>", "([BLjava/lang/String;)V")); + ary = (*env)->NewByteArray(env, len); + if (ary != 0) { + jstring str = 0; + (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); + if (!(*env)->ExceptionOccurred(env)) { + utf8 = (*env)->NewStringUTF(env, "UTF-8"); + if (utf8 != 0) { + str = (*env)->NewObject(env, cls, mid, ary, utf8); + } + (*env)->DeleteLocalRef(env, utf8); + } + (*env)->DeleteLocalRef(env, ary); + return str; + } + return 0; + } + /* * Returns a new Java string object for the specified platform string. */ ====================================================================== ###@###.### 2004-04-21 Although the above fix is probably valid, the fix being used is to remove the minor optimization which caused this. The above fix may be used in the future. The actual change: ------- java.c ------- 2c2 < * @(#)java.c 1.115 04/03/15 --- > * @(#)java.c 1.116 04/04/21 98a99 > static jstring GetMainClassName(JNIEnv *env, char *jarname); 188a190,191 > * (Note: This side effect has been disabled. See comment on > * bugid 5030265 below.) 324c327,346 < /* Get the application's main class */ --- > /* > * Get the application's main class. > * > * See bugid 5030265. The Main-Class name has already been parsed > * from the manifest, but not parsed properly for UTF-8 support. > * Hence the code here ignores the value previously extracted and > * uses the pre-existing code to reextract the value. This is > * possibly an end of release cycle expedient. However, it has > * also been discovered that passing some character sets through > * the environment has "strange" behavior on some variants of > * Windows. Hence, maybe the manifest parsing code local to the > * launcher should never be enhanced. > * > * Hence, future work should either: > * 1) Correct the local parsing code and verify that the > * Main-Class attribute gets properly passed through > * all environments, > * 2) Remove the vestages of maintaining main_class through > * the environment (and remove these comments). > */ 326c348,353 < if (main_class == NULL) { --- > mainClassName = GetMainClassName(env, jarfile); > if ((*env)->ExceptionOccurred(env)) { > ReportExceptionDescription(env); > goto leave; > } > if (mainClassName == NULL) { 335d361 < mainClassName = NewPlatformString(env, main_class); 1104a1131,1169 > > /* > * Returns the main class name for the specified jar file. > */ > static jstring > GetMainClassName(JNIEnv *env, char *jarname) > { > #define MAIN_CLASS "Main-Class" > jclass cls; > jmethodID mid; > jobject jar, man, attr; > jstring str, result = 0; > > NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile")); > NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>", > "(Ljava/lang/String;)V")); > NULL_CHECK0(str = NewPlatformString(env, jarname)); > NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str)); > NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest", > "()Ljava/util/jar/Manifest;")); > man = (*env)->CallObjectMethod(env, jar, mid); > if (man != 0) { > NULL_CHECK0(mid = (*env)->GetMethodID(env, > (*env)->GetObjectClass(env, man), > "getMainAttributes", > "()Ljava/util/jar/Attributes;")); > attr = (*env)->CallObjectMethod(env, man, mid); > if (attr != 0) { > NULL_CHECK0(mid = (*env)->GetMethodID(env, > (*env)->GetObjectClass(env, attr), > "getValue", > "(Ljava/lang/String;)Ljava/lang/String;")); > NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS)); > result = (*env)->CallObjectMethod(env, attr, mid, str); > } > } > return result; > } >
11-06-2004

PUBLIC COMMENTS Internal development bug (also present in 1.5 beta 1)
10-06-2004