2012-05-19 8 views
8

Java 6では、ScalaでJNIを使​​用できました。私のようなコードを持っているでしょう:Java 7でScalaでJNIを書くときにjavahでエラーが発生する

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$ 
をそして、私は私のヘッダファイルがうまく取得したいです。 Javaの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は、もはやクラス名にドル記号を受け入れるようにですませんが、私は、静的と同等のものを得るために、Scalaでドル記号を使用する必要があります方法。 Javaの6と参照用

:Javaの7付

$ 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" 

$ 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" 

誰にJava 7にスカラ座とJNIのためのjavahを使って任意の運を持っていましたか?バグとして投稿

編集

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7185778

答えて

5

で何が起こっているかのいくつかの理解を得るための最良の方法は、直接、OpenJDKのウェブサイトを通じてソースに行くことです。だから今のは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; 
    } 
に見てみましょう

if (!SourceVersion.isName(cls)) // implicit null check 
         throw new IllegalArgumentException("Not a valid class name: " + cls); 

:我々は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()); 
} 

}

に見ればあなたは、問題のある行を見ることができます

私たちが期待していた方法が真実であることが分かります

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; 
    } 

そして、我々は1.6バージョンに見れば問題は今!Character.isJavaIdentifierPart(cp)

です::E)である

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をに目を向けるならば、それはJavaの分布を構築する際/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; 
     } 
    } 
} 

javahをデバッグモードで実行して、2つのケースで何が起こるかを見て、OpenJDKの人に正確なバグレポートを送ることができます。バグがこのリファクタリングによって明確に導入されているからです。

+1

ありがとう、私はOpenJDKにバグを報告しました。https://bugs.openjdk.java.net/show_bug.cgi?id=100267 – Mike

+0

bugreport.sun.comに再送信しました。彼らが応答すると返信します。 – Mike

関連する問題