सबसे अच्छा तरीका है पर एक बग के रूप में प्रकाशित किया गया था। अगर हम करने के लिए com.sun.tools.javac.api.JavacTool
public JavacTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes,
Iterable<? extends JavaFileObject> compilationUnits)
{
try {
Context context = new Context();
ClientCodeWrapper ccw = ClientCodeWrapper.instance(context);
final String kindMsg = "All compilation units must be of SOURCE kind";
if (options != null)
for (String option : options)
option.getClass(); // null check
if (classes != null) {
for (String cls : classes)
if (!SourceVersion.isName(cls)) // implicit null check
throw new IllegalArgumentException("Not a valid class name: " + cls);
}
if (compilationUnits != null) {
compilationUnits = ccw.wrapJavaFileObjects(compilationUnits); // implicit null check
for (JavaFileObject cu : compilationUnits) {
if (cu.getKind() != JavaFileObject.Kind.SOURCE)
throw new IllegalArgumentException(kindMsg);
}
}
if (diagnosticListener != null)
context.put(DiagnosticListener.class, ccw.wrap(diagnosticListener));
if (out == null)
context.put(Log.outKey, new PrintWriter(System.err, true));
else
context.put(Log.outKey, new PrintWriter(out, true));
if (fileManager == null)
fileManager = getStandardFileManager(diagnosticListener, null, null);
fileManager = ccw.wrap(fileManager);
context.put(JavaFileManager.class, fileManager);
processOptions(context, fileManager, options);
Main compiler = new Main("javacTask", context.get(Log.outKey));
return new JavacTaskImpl(compiler, options, context, classes, compilationUnits);
} catch (ClientCodeException ex) {
throw new RuntimeException(ex.getCause());
}
}
देखो आप उल्लंघन करने वाली लाइन देख सकते हैं:
if (!SourceVersion.isName(cls)) // implicit null check
throw new IllegalArgumentException("Not a valid class name: " + cls);
तो अब चलो javax.lang.model.SourceVersion
को
/**
* Returns whether or not {@code name} is a syntactically valid
* qualified name in the latest source version. Unlike {@link
* #isIdentifier isIdentifier}, this method returns {@code false}
* for keywords and literals.
*
* @param name the string to check
* @return {@code true} if this string is a
* syntactically valid name, {@code false} otherwise.
* @jls 6.2 Names and Identifiers
*/
public static boolean isName(CharSequence name) {
String id = name.toString();
for(String s : id.split("\\.", -1)) {
if (!isIdentifier(s) || isKeyword(s))
return false;
}
return true;
}
एक नजर है
तो आप देख सकते हैं कि जिस विधि को हम सही लौटने की उम्मीद कर रहे थे (लेकिन बदले में झूठी वापसी ई) है:
public static boolean isIdentifier(CharSequence name) {
String id = name.toString();
if (id.length() == 0) {
return false;
}
int cp = id.codePointAt(0);
if (!Character.isJavaIdentifierStart(cp)) {
return false;
}
for (int i = Character.charCount(cp);
i < id.length();
i += Character.charCount(cp)) {
cp = id.codePointAt(i);
if (!Character.isJavaIdentifierPart(cp)) {
return false;
}
}
return true;
}
और समस्या !Character.isJavaIdentifierPart(cp)
अगर हम 1.6 संस्करण के लिए लग रही है अब:
public static boolean isJavaIdentifierPart(int codePoint) {
boolean bJavaPart = false;
if (codePoint >= MIN_CODE_POINT && codePoint <= FAST_PATH_MAX) {
bJavaPart = CharacterDataLatin1.isJavaIdentifierPart(codePoint);
} else {
int plane = getPlane(codePoint);
switch(plane) {
case(0):
bJavaPart = CharacterData00.isJavaIdentifierPart(codePoint);
break;
case(1):
bJavaPart = CharacterData01.isJavaIdentifierPart(codePoint);
break;
case(2):
bJavaPart = CharacterData02.isJavaIdentifierPart(codePoint);
break;
case(3): // Undefined
case(4): // Undefined
case(5): // Undefined
case(6): // Undefined
case(7): // Undefined
case(8): // Undefined
case(9): // Undefined
case(10): // Undefined
case(11): // Undefined
case(12): // Undefined
case(13): // Undefined
bJavaPart = CharacterDataUndefined.isJavaIdentifierPart(codePoint);
break;
case(14):
bJavaPart = CharacterData0E.isJavaIdentifierPart(codePoint);
break;
case(15): // Private Use
case(16): // Private Use
bJavaPart = CharacterDataPrivateUse.isJavaIdentifierPart(codePoint);
break;
default:
// the argument's plane is invalid, and thus is an invalid codepoint
// bJavaPart remains false;
break;
}
}
return bJavaPart;
}
और 1।7 संस्करण:
public static boolean isJavaIdentifierPart(int codePoint) {
return CharacterData.of(codePoint).isJavaIdentifierPart(codePoint);
}
कुछ पुनर्रचना के यहाँ आ गई है, और यदि आप CharacterData को देखने की आपको लगता है कि यह कुछ वर्ग है जो /openjdk/make/tools/GenerateCharacter/CharacterData**.java.template
में खाके से जेनरेट कर रहे हैं जब जावा वितरण के निर्माण के रिटर्न की खोज:
// Character <= 0xff (basic latin) is handled by internal fast-path
// to avoid initializing large tables.
// Note: performance of this "fast-path" code may be sub-optimal
// in negative cases for some accessors due to complicated ranges.
// Should revisit after optimization of table initialization.
static final CharacterData of(int ch) {
if (ch >>> 8 == 0) { // fast-path
return CharacterDataLatin1.instance;
} else {
switch(ch >>> 16) { //plane 00-16
case(0):
return CharacterData00.instance;
case(1):
return CharacterData01.instance;
case(2):
return CharacterData02.instance;
case(14):
return CharacterData0E.instance;
case(15): // Private Use
case(16): // Private Use
return CharacterDataPrivateUse.instance;
default:
return CharacterDataUndefined.instance;
}
}
}
मुझे लगता है कि आप डीबग मोड में जावा चलाने की कोशिश कर सकते हैं और देख सकते हैं कि दो मामलों में क्या होता है, फिर ओपनजेडीके लोगों को एक सटीक बग रिपोर्ट भेजें, क्योंकि इस रीफैक्टरिंग द्वारा बग स्पष्ट रूप से पेश किया गया है।
धन्यवाद, मैं सिर्फ https://bugs.openjdk.java.net/show_bug.cgi?id=100267 पर OpenJDK के लिए एक बग – Mike
bugreport.sun.com पास पुन: प्रस्तुत की सूचना दी। अगर वे जवाब देंगे तो वापस पोस्ट करेंगे। – Mike