2012-05-19 15 views
8

जावा 6 में, मैं स्कैला में जेएनआई का उपयोग ठीक करने में सक्षम था। मैं की तरह कोड होगा:जावा के साथ स्कैला में जेएनआई लिखते समय जावा के साथ त्रुटि 7

package mypackage 
object MyClass { 
    System.loadLibrary("myclass-native") 
    @native def foo(): Int = sys.error("") 
} 

और फिर मैं चलाने चाहते हैं:

javah -classpath target/scala-2.9.1/classes -d target/jni mypackage.MyClass$ 

और मैं अपने हेडर फाइल ठीक मिल चाहते हैं।

जावा 7 में, मैं निम्नलिखित त्रुटि मिलती है:

Exception in thread "main" java.lang.IllegalArgumentException: Not a valid class name: mypackage.MyClass. 
at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:177) 
at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:68) 
at com.sun.tools.javah.JavahTask.run(JavahTask.java:509) 
at com.sun.tools.javah.JavahTask.run(JavahTask.java:335) 
at com.sun.tools.javah.Main.main(Main.java:46) 

यह javah की तरह है नहीं रह गया है स्वीकार करता है वर्ग के नाम में डॉलर चिह्न, लेकिन मैं स्काला में डॉलर चिह्न का उपयोग करने के लिए एक स्थिर के बराबर प्राप्त करने की आवश्यकता तरीका।

संदर्भ के लिए जावा 6 के साथ:

$ java -version 
java version "1.6.0_29" 
Java(TM) SE Runtime Environment (build 1.6.0_29-b11) 
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode) 
$ javah -version 
javah version "1.6.0_29" 
जावा 7 के साथ

:

$ java -version 
java version "1.7.0_03" 
OpenJDK Runtime Environment (IcedTea7 2.1.1pre) (7~u3-2.1.1~pre1-1ubuntu2) 
OpenJDK 64-Bit Server VM (build 22.0-b10, mixed mode) 
$ javah -version 
javah version "1.7.0_03" 

किसी को भी जावा 7 में स्काला साथ JNI के लिए javah उपयोग कर किसी भी किस्मत ने गया है?

संपादित

क्या हो रहा है सीधे OpenJDK वेबसाइट के माध्यम से सूत्रों के जाने के लिए है में से कुछ समझ पाने के लिए http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7185778

उत्तर

5

सबसे अच्छा तरीका है पर एक बग के रूप में प्रकाशित किया गया था। अगर हम करने के लिए 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; 
     } 
    } 
} 

मुझे लगता है कि आप डीबग मोड में जावा चलाने की कोशिश कर सकते हैं और देख सकते हैं कि दो मामलों में क्या होता है, फिर ओपनजेडीके लोगों को एक सटीक बग रिपोर्ट भेजें, क्योंकि इस रीफैक्टरिंग द्वारा बग स्पष्ट रूप से पेश किया गया है।

+1

धन्यवाद, मैं सिर्फ https://bugs.openjdk.java.net/show_bug.cgi?id=100267 पर OpenJDK के लिए एक बग – Mike

+0

bugreport.sun.com पास पुन: प्रस्तुत की सूचना दी। अगर वे जवाब देंगे तो वापस पोस्ट करेंगे। – Mike

संबंधित मुद्दे