2009-08-18 16 views
34

クラスファイルがコンパイルされるJDKのバージョンを調べるJava APIはありますか?もちろん、hereで言及されているメジャーバージョンを見つけるためのjavapツールがあります。しかし、私はそれをプログラム的に実行して、適切なJDKのためにコンパイルするよう警告することができます。クラスファイルがコンパイルされているJDKのバージョンを調べるJava API?

+1

ファイルからバイトを読み取るのに必要な答えは、私にはあまりにも文句がないようです。 Foobar.class.getTargetVersion()など、Reflectionを使用してこの情報を取得する方法があります。 –

答えて

45
import java.io.*; 
public class ClassVersionChecker { 
public static void main(String[] args) throws IOException { 
    for (int i = 0; i < args.length; i++) 
     checkClassVersion(args[i]); 
} 

    private static void checkClassVersion(String filename) 
     throws IOException 
    { 
     DataInputStream in = new DataInputStream 
     (new FileInputStream(filename)); 

     int magic = in.readInt(); 
     if(magic != 0xcafebabe) { 
      System.out.println(filename + " is not a valid class!");; 
     } 
     int minor = in.readUnsignedShort(); 
     int major = in.readUnsignedShort(); 
     System.out.println(filename + ": " + major + " . " + minor); 
     in.close(); 
    } 
} 

可能な値は以下のとおりです。

major minor Java platform version 
45  3   1.0 
45  3   1.1 
46  0   1.2 
47  0   1.3 
48  0   1.4 
49  0   5 
50  0   6 
51  0   7 
52  0   8 
53  0   9 
0

JavaPにはAPIがありますが、それはSun JDK固有のものです。

tools.jarsun/tools/javap/Main.classにあります。

8

これはあなたのクラスファイルの内容を取得します:

MysteryClass.class.getResourceAsStream("MysteryClass.class")

その後、マイナーを取得するために、バイト5-8を見て、メジャーバージョン。それらの番号とJDKリリースとのマッピングはhereです。

+0

文字列引数を完全修飾する必要がありますか? getResourceAsStream( "org/apache/foobar/Whatever.class")? –

+0

いいえ、リソースを取得するための基礎としてクラス自体を使用しているためです。クラスの代わりにClassLoaderのgetResourceメソッドを使用できる場合は、完全修飾名が必要です。 –

5

クラスファイルを直接読み込んでください。それは非常にバージョンを把握するのは簡単です。 specwikiを確認してから、コードを試してください。このコードをラップして作ることは、より便利です/かなり練習として残っています。他の人が示したように別の方法として、あなたはBCELASM、またはJavaAssist

import java.io.DataInputStream; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 

public class ClassVersionTest 
{ 
    private static final int JAVA_CLASS_MAGIC = 0xCAFEBABE; 

    public static void main(String[] args) 
    { 
     try 
     { 
      DataInputStream dis = new DataInputStream(new FileInputStream("Test.class")); 
      int magic = dis.readInt(); 
      if(magic == JAVA_CLASS_MAGIC) 
      { 
       int minorVersion = dis.readUnsignedShort(); 
       int majorVersion = dis.readUnsignedShort(); 

       /** 
       * majorVersion is ... 
       * J2SE 6.0 = 50 (0x32 hex), 
       * J2SE 5.0 = 49 (0x31 hex), 
       * JDK 1.4 = 48 (0x30 hex), 
       * JDK 1.3 = 47 (0x2F hex), 
       * JDK 1.2 = 46 (0x2E hex), 
       * JDK 1.1 = 45 (0x2D hex). 
       */ 

       System.out.println("ClassVersionTest.main() " + majorVersion + "." + minorVersion); 
      } 
      else 
      { 
       // not a class file 
      } 
     } 
     catch (FileNotFoundException e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     catch (IOException e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

} 
+0

これは、jarファイル内のクラスファイルに対して機能しますか? –

2

のようなライブラリを使用することができ、クラスファイルの最初の8つのバイトを読み込むことで行うのに十分に簡単です。あらかじめ構築されたバイナリライブラリが必要な場合は、hereをダウンロードできます。

7

Apache BCELは、このAPIを提供します:

JavaClass c = Repository.lookupClass("com.x.MyClass") 
c.getMinor(); 
c.getMajor(); 
17

basszeroのアプローチは、UNIXのコマンドラインを介して行うことができ、かつ "OD(1)" コマンド:

% od -x HelloWorldJava.class |head -2 
0000000 feca beba 0000 3100 dc00 0007 0102 2a00 
0000020 6f63 2f6d 6e65 6564 6163 642f 6d65 2f6f 

"FECAのBEBAは" magic number。 「0000 3100」は、J2SE 5.0を表す0x31です。

2

Linuxでは、クラスファイルでfileコマンドを使用することができます。これは私の使用例で最も簡単なものです。例:

$ file Foo.class 
Foo.class: compiled Java class data, version 50.0 (Java 1.6) 
関連する問題