2009-08-18 39 views
34

Có bất kỳ API Java nào để tìm phiên bản JDK mà một tệp lớp được biên dịch không? Tất nhiên có công cụ javap để tìm ra phiên bản chính như đã đề cập trong here. Tuy nhiên tôi muốn làm điều đó theo chương trình để tôi có thể cảnh báo người dùng biên dịch nó cho JDKJava API để tìm phiên bản JDK một tệp lớp được biên dịch?

+1

Câu trả lời liên quan đến việc đọc byte từ một tệp có vẻ khá không được giải thích với tôi. Có phải là một cách để có được thông tin này bằng cách sử dụng Reflection, chẳng hạn như Foobar.class.getTargetVersion(). –

Trả lời

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

Các giá trị có thể là:

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 hiện có API, nhưng nó cụ thể đối với JDK của Mặt trời.

Nó được tìm thấy trong tools.jar, dưới sun/tools/javap/Main.class.

8

này giúp bạn các nội dung của tập tin lớp:

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

Sau đó nhìn vào byte 5-8 để có được trẻ vị thành niên và phiên bản chính. Một bản đồ giữa các số đó và các bản phát hành JDK có thể được tìm thấy here.

+0

Đối số chuỗi có cần phải đủ điều kiện không? getResourceAsStream ("org/apache/foobar/Whatever.class")? –

+0

Không, vì bạn đang sử dụng chính lớp đó làm cơ sở để nhận tài nguyên. Bạn cần tên đầy đủ nếu bạn có thể lấy các phương thức nguồn của ClassLoader thay vì một lớp. –

5

Chỉ cần đọc trực tiếp tệp lớp học. Nó rất dễ dàng để tìm ra phiên bản. Hãy xem specwiki rồi thử mã. Gói mã này và làm cho hữu ích hơn/khá là trái như một bài tập. Ngoài ra, bạn có thể sử dụng một thư viện như BCEL, ASM, hoặc 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

Thao tác này có hoạt động đối với các tệp lớp trong một cái lọ không? –

2

Như những người khác đã chỉ ra, nó là đủ dễ dàng để làm bằng cách đọc số tám byte đầu tiên của một tập tin lớp. Nếu bạn muốn có một thư viện nhị phân dựng sẵn, bạn có thể tải xuống một here.

7

Apache BCEL cung cấp API này:

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

cách tiếp cận basszero có thể được thực hiện thông qua các dòng lệnh UNIX, và "od (1)" lệnh:

% 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" là magic number. "0000 3100" là 0x31, đại diện cho J2SE 5.0.

2

Trên Linux, bạn có thể sử dụng lệnh file trên tệp lớp mà tôi thấy dễ dàng nhất cho trường hợp sử dụng của mình. Ví dụ:

$ file Foo.class 
Foo.class: compiled Java class data, version 50.0 (Java 1.6) 
Các vấn đề liên quan