Javac รุ่นใดที่ฉันสร้างไห


212

ฉันจะบอกได้อย่างไรว่าคอมไพเลอร์ Java รุ่นใดที่ใช้สร้างขวด? ฉันมีไฟล์ jar และมันสามารถสร้างได้ในหนึ่งในสามของ JDK เราจำเป็นต้องรู้ว่าต้องใช้อันไหนเพื่อที่จะรับรองความเข้ากันได้ เวอร์ชั่นคอมไพเลอร์ฝังอยู่ที่ไหนสักแห่งในไฟล์คลาสหรือ jar?


8
คุณสามารถบอก verson หลักโดยดูที่ไฟล์ Manifest คุณสามารถบอกรุ่นเป้าหมายได้โดยดูที่คลาสไฟล์เอง แต่ JDK สามารถสร้างคลาสไฟล์สำหรับจาวารุ่นก่อนหน้าโดยใช้ตัวเลือก -target ดังนั้นการดูที่ไบต์แรกอาจไม่แม่นยำ
— Peter Lawrey

15
ใน MANIFEST.MF คุณสามารถค้นหาสิ่งที่ต้องการCreated-By: 1.7.0_13 (Oracle Corporation)
— hko19

1
ดูเหมือนว่า Maven 3 จะทำสิ่งนี้Created-By: Apache MavenและBuild-Jdk: 1.8.0_25
— Neal Xiong

โปรดตรวจสอบสิ่งนี้: stackoverflow.com/questions/27065/…
— Abheek Dutta

คำตอบ:


89

คุณไม่สามารถบอกได้จากไฟล์ JAR เอง

ดาวน์โหลด hex editor และเปิดหนึ่งในคลาสไฟล์ภายใน JAR และดูที่ byte offsets 4 ถึง 7 ข้อมูลเวอร์ชันถูกสร้างขึ้น

http://en.wikipedia.org/wiki/Java_class_file

หมายเหตุ: ตามที่ระบุไว้ในความคิดเห็นด้านล่าง

ไบต์เหล่านั้นบอกให้คุณทราบว่าเวอร์ชันใดที่คลาสได้รับการคอมไพล์ให้ไม่ใช่เวอร์ชันที่คอมไพล์แล้ว


41
เมื่อต้องการเป็นอนาจารไบต์เหล่านั้นจะบอกคุณว่าเวอร์ชันใดที่คลาสได้รับการคอมไพล์แล้วไม่ใช่เวอร์ชันใดที่คอมไพล์แล้ว Java อนุญาตให้คุณรวบรวมรหัสเพื่อให้สามารถทำงานร่วมกับ Java เวอร์ชันก่อนหน้าได้ อย่างไรก็ตามสิ่งนี้ใช้ได้กับรหัสไบต์และรูปแบบเท่านั้น มันจะรวบรวมรหัสอย่างมีความสุขที่อ้างอิงไลบรารี JDK 6 เป็นรูปแบบ JDK 5 ตัวอย่างเช่น JDK 5 จะโหลดคลาส แต่ไม่สามารถเรียกใช้ได้เนื่องจากไลบรารี JDK 5 ไม่มีรหัสอ้างอิงจาก JDK 6
— Will Hartung

6
เราสามารถค้นหาได้ในไฟล์รายการไฟล์ที่สร้างโดย: 1.7.0_21-b11 (Oracle Corporation)
— กฤษณะ

8
คำตอบอื่น ๆบอกวิธีการตรวจสอบง่าย ๆ ผ่านบรรทัดคำสั่ง
— mgarciaisaia

313

A jarเป็นเพียงภาชนะบรรจุ มันเป็นไฟล์ที่เก็บ a tarla แม้ว่า a jarอาจมีข้อมูลที่น่าสนใจที่อยู่ในลำดับชั้นของMETA-INFแต่ก็ไม่มีข้อผูกมัดใด ๆ ในการระบุความเก่าแก่ของชั้นเรียนภายในเนื้อหา เพื่อที่หนึ่งจะต้องตรวจสอบclassไฟล์ในนั้น

ดังที่Peter Lawreyพูดถึงในการแสดงความคิดเห็นกับคำถามเดิมคุณไม่สามารถรู้ได้เลยว่า JDK รุ่นใดที่สร้างclassไฟล์ที่กำหนดแต่คุณสามารถค้นหารุ่นคลาสของรหัสไบต์ของclassไฟล์ที่อยู่ในjarไฟล์ที่มีอยู่ใน

ใช่นี้นะครับ jarแต่ขั้นตอนแรกคือการดึงหนึ่งหรือมากกว่าหนึ่งชั้นเรียนจาก ตัวอย่างเช่น:

$ jar xf log4j-1.2.15.jar

บน Linux, Mac OS X หรือ Windows ที่ติดตั้งCygwinคำสั่งfile (1) จะรู้รุ่นของคลาส

$ file ./org/apache/log4j/Appender.class
./org/apache/log4j/Appender.class: compiled Java class data, version 45.3

หรือมิฉะนั้นให้ใช้javapจาก JDK เป็น @ jikes.thunderbolt aptly ชี้ให้เห็น:

$ javap -v ./org/apache/log4j/Appender.class | grep major
 major version: 45

และถ้าคุณถูกผลักไสให้เข้ากับWindowsสภาพแวดล้อมที่ไม่มีfileหรือgrep

> javap -v ./org/apache/log4j/Appender.class | findstr major
 major version: 45

FWIW ฉันจะเห็นด้วยที่javapจะบอกรายละเอียดทั้งหมดเกี่ยวกับที่ได้รับclassไฟล์ที่มากกว่าคำถามเดิมที่ถาม

อย่างไรก็ตามรุ่นคลาสอื่น ๆ เช่น:

$ file ~/bin/classes/P.class
/home/dave/bin/classes/P.class: compiled Java class data, version 50.0

หมายเลขคลาสเวอร์ชันหลักสอดคล้องกับเวอร์ชัน Java JDK ต่อไปนี้:

  • 45.3 = Java 1.1
  • 46 = Java 1.2
  • 47 = Java 1.3
  • 48 = Java 1.4
  • 49 = Java 5
  • 50 = Java 6
  • 51 = Java 7
  • 52 = Java 8
  • 53 = Java 9

7
รุ่นของฉันfileไม่ได้แสดงให้เห็นว่า hexdump ~/bin/classes/P.class | headแต่ฉันก็สามารถที่จะตรวจสอบในชั้นเรียนด้วยตนเองด้วยคำสั่งนี้ เพียงแค่ดูที่แปดไบต์และแปลงเป็นทศนิยม
— Jarett Millard

2
ดูเหมือนว่า 'ไฟล์' ของ FYI จะขึ้นอยู่กับรุ่นของ Java ว่าจะแสดงรุ่น JDK หรือไม่ ใน CentOS / Oracle Linux และคลาสที่คอมไพล์ Java 6 ฉันได้รับ "รวบรวมคลาสคลาส Java, เวอร์ชัน 50.0 (Java 1.6)" แต่เมื่อฉันรันคลาสที่คอมไพล์ด้วย Java 7 ฉันเพิ่งได้รับรุ่นทั่วไป "รวบรวมคลาสคลาส Java รุ่น 51.0 "
— Dan Haynes

1
JAR=something.jar ; unzip -p $JAR `unzip -l $JAR | grep '\.class$' | head -1` | file -
— Randall Whitman

3
@JarettMillard cygwin ของฉันfile file.class(5.22-1) ไม่ได้แสดงเป้าหมายคลาส java ในตอนแรก: "file.class: [architecture = 6909806] [Architecture = 6845039]" อย่างไรก็ตามfile -k file.classทำเช่นนั้น: "file.class: [architecture = 6909806] [architecture = 6845039] ข้อมูลคลาส Java ที่คอมไพล์แล้วรุ่น 50.0 (Java 1.6)" ดูเหมือนว่าfileมีเพียงการแข่งขันครั้งแรกใน magicfiles -kของฐานข้อมูลโดยไม่ต้อง
— สลัว

1
การใช้ "javap -p <class> | grep major" ไม่น่าเชื่อถือ หาก pom.xml มีแหล่งที่มา / เป้าหมาย 1.7, javap จะให้ "รุ่นหลัก: 51" กับคุณเสมอไม่ว่าคุณจะใช้ JDK 1.7, JDK 1.8 หรือ JDK 1.9 เพื่อรวบรวม
— user2569618

54

นี่คือวิธีของ Java ในการค้นหาข้อมูลนี้

ของ windows: javap -v <class> | findstr major
Unix:javap -v <class> | grep major

ตัวอย่างเช่น:
> javap -v Application | findstr major   major version: 51


3
จากคำตอบทั้งหมดคำตอบของคุณสั้นกระชับที่สุดและไม่เกี่ยวข้องกับการเขียนรหัส 10 บรรทัดเพื่อทราบข้อมูลรุ่น +1 สำหรับสิ่งนั้น
— ธี

2
<class>พารามิเตอร์คืออะไร
— Dims

1
@Dims ไฟล์ ".class" ที่คุณพยายามค้นหารุ่น ในตัวอย่างของเขาเขามีApplication.classไฟล์และมันกลับกลายเป็นคอมไพล์สำหรับ Java 7 ( major version: 51)
— inanutshellus

1
คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

15

ไม่จำเป็นต้องแยกบรรจุ JAR (ถ้ามีชื่อคลาสอย่างใดอย่างหนึ่งหรือเป็นที่รู้จักเช่นใช้ 7zip) ดังนั้นสำหรับ Windows ต่อไปนี้จะเพียงพอ:

javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major

1
ใช้งานได้กับ linux ด้วย (ยกเว้นคุณใช้ grep แทน findstr แน่นอน)
— Michael Rusch

1
คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

15

คอมไพเลอร์ Java ( javac) ไม่สร้างไห แต่แปลไฟล์ Java เป็นไฟล์คลาส เครื่องมือ Jar ( jar) สร้างไหจริง หากไม่ได้ระบุรายการที่กำหนดเองรายการเริ่มต้นจะระบุว่ารุ่นใดของ JDK ที่ใช้ในการสร้างขวด


3
ในขณะที่เป็นจริงสิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม
— zb226

2
@ zb226 AFAIK รุ่นของคอมไพเลอร์ที่ใช้ในการรวบรวมการเรียนที่ไม่สามารถหาได้จากไฟล์ชั้นเพียงรุ่นที่เรียนถูกรวบรวมสำหรับ ข้อมูลที่ฉันให้มีเพียงข้อมูล (มาตรฐาน) ที่มีอยู่เกี่ยวกับรุ่นที่สร้างสิ่งประดิษฐ์ หากไม่ใช่สิ่งที่ถูกถามคำถามนั้นควรเป็นคำใหม่
— jackrabbit

ตกลงฉันกำลังดูที่จากมุมมองเชิงปฏิบัติ แต่ฉันเห็นจุดของคุณตอนนี้ downvote ลบ :)
— zb226

9

เนื่องจากฉันต้องการวิเคราะห์ขวดไขมันฉันจึงสนใจรุ่นของแต่ละคลาสในไฟล์ jar ดังนั้นฉันจึงใช้วิธี Joe Liversedge https://stackoverflow.com/a/27877215/1497139และรวมเข้ากับ David J. Liszewski ' https://stackoverflow.com/a/3313839/1497139ตารางหมายเลขเวอร์ชันของคลาสเพื่อสร้างสคริปต์ทุบตี jarv เพื่อแสดงเวอร์ชันของไฟล์คลาสทั้งหมดในไฟล์ jar

การใช้

usage: ./jarv jarfile
 -h|--help: show this usage

ตัวอย่าง

jarv $Home/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar

java 1.4 org.apache.log4j.Appender
java 1.4 org.apache.log4j.AppenderSkeleton
java 1.4 org.apache.log4j.AsyncAppender$DiscardSummary
java 1.4 org.apache.log4j.AsyncAppender$Dispatcher
...

Bash script jarv

#!/bin/bash
# WF 2018-07-12
# find out the class versions with in jar file
# see https://stackoverflow.com/questions/3313532/what-version-of-javac-built-my-jar

# uncomment do debug
# set -x

#ansi colors
#http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html
blue='\033[0;34m'  
red='\033[0;31m'  
green='\033[0;32m' # '\e[1;32m' is too bright for white bg.
endColor='\033[0m'

#
# a colored message 
#   params:
#     1: l_color - the color of the message
#     2: l_msg - the message to display
#
color_msg() {
  local l_color="$1"
  local l_msg="$2"
  echo -e "${l_color}$l_msg${endColor}"
}

#
# error
#
#   show an error message and exit
#
#   params:
#     1: l_msg - the message to display
error() {
  local l_msg="$1"
  # use ansi red for error
  color_msg $red "Error: $l_msg" 1>&2
  exit 1
}

#
# show the usage
#
usage() {
  echo "usage: $0 jarfile"
  # -h|--help|usage|show this usage
  echo " -h|--help: show this usage"
  exit 1 
}

#
# showclassversions
#
showclassversions() {
  local l_jar="$1"
  jar -tf "$l_jar" | grep '.class' | while read classname
  do
    class=$(echo $classname | sed -e 's/\.class$//')
    class_version=$(javap -classpath "$l_jar" -verbose $class | grep 'major version' | cut -f2 -d ":" | cut -c2-)
    class_pretty=$(echo $class | sed -e 's#/#.#g')
    case $class_version in
      45.3) java_version="java 1.1";;
      46) java_version="java 1.2";;
      47) java_version="java 1.3";;
      48) java_version="java 1.4";;
      49) java_version="java5";;
      50) java_version="java6";;
      51) java_version="java7";;
      52) java_version="java8";;
      53) java_version="java9";;
      54) java_version="java10";;
      *) java_version="x${class_version}x";;
    esac
    echo $java_version $class_pretty
  done
}

# check the number of parameters
if [ $# -lt 1 ]
then
  usage
fi

# start of script
# check arguments
while test $# -gt 0
do
  case $1 in
    # -h|--help|usage|show this usage
    -h|--help) 
      usage
      exit 1
      ;;
    *)
     showclassversions "$1"
  esac
  shift
done 

1
สุดยอดสคริปต์! ฉันสามารถตรวจสอบไหจาวาได้
— ARK

ขอบคุณมากสำหรับการแบ่งปันสคริปต์! เพียงคำใบ้จากด้านข้างของฉัน head -1อาจใช้ร่วมกับสคริปต์: โดยปกติจะเพียงพอที่จะดูเวอร์ชันของคลาสแรกในไฟล์ jar
— Sergey Brunov

7

คุณสามารถค้นหาเวอร์ชันคอมไพเลอร์ Java จากไฟล์. class โดยใช้ Hex Editor

ขั้นตอนที่ 1: แยกไฟล์. class ออกจากไฟล์ jar โดยใช้ตัวแยกไฟล์ zip

ขั้นตอนที่ 2: เปิดไฟล์. class ด้วย hex editor (ฉันใช้ notepad ++ hex editor plugin ปลั๊กอินนี้อ่านไฟล์เป็น binary และแสดงเป็น hex) คุณสามารถดูด้านล่าง ป้อนคำอธิบายรูปภาพที่นี่

ดัชนี 6 และ 7 ให้หมายเลขรุ่นหลักของรูปแบบไฟล์คลาสที่ใช้ https://en.wikipedia.org/wiki/Java_class_file

Java SE 11 = 55 (0x37 ฐานสิบหก)

Java SE 10 = 54 (0x36 ฐานสิบหก)

Java SE 9 = 53 (0x35 ฐานสิบหก)

Java SE 8 = 52 (0x34 ฐานสิบหก)

Java SE 7 = 51 (0x33 ฐานสิบหก)

Java SE 6.0 = 50 (0x32 ฐานสิบหก)

Java SE 5.0 = 49 (0x31 hex)

JDK 1.4 = 48 (0x30 ฐานสิบหก)

JDK 1.3 = 47 (ฐานสิบหก 0x2F)

JDK 1.2 = 46 (ฐานสิบหก 0x2E)

JDK 1.1 = 45 (ฐานสิบหก 0x2D)


4

คุณสามารถบอกรุ่นไบนารีของ Java โดยตรวจสอบ 8 ไบต์แรก (หรือใช้แอพที่สามารถทำได้)

คอมไพเลอร์เองก็ไม่ได้ใส่ความรู้ลงไปในสิ่งที่ดีที่สุด ฉันไม่สามารถมองเห็นสิ่งต่าง ๆ ในรูปแบบคลาสข้อมูลจำเพาะของ VM ของไฟล์ได้


คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

4

รหัสโพสต์โดยโอเว่นสามารถบอกคุณได้ข้อมูลดังกล่าวเป็นจำนวนมากโดยคำตอบอื่น ๆ ที่นี่:

public void simpleExample ()
{
    FileInputStream fis = new FileInputStream ("mytest.class");
    parseJavaClassFile ( fis );
}
protected void parseJavaClassFile ( InputStream classByteStream ) throws Exception
{
    DataInputStream dataInputStream = new DataInputStream ( classByteStream );
    magicNumber = dataInputStream.readInt();
    if ( magicNumber == 0xCAFEBABE )
    {
        int minorVer = dataInputStream.readUnsignedShort();
        int majorVer = dataInputStream.readUnsignedShort();
        // do something here with major & minor numbers
    }
}

ดูเพิ่มเติมนี้และนี้เว็บไซต์ ฉันสิ้นสุดการปรับเปลี่ยนรหัสผลิตภัณฑ์ใจได้อย่างรวดเร็วเพื่อตรวจสอบสิ่งที่อ้างอิงของฉันแต่ละรวบรวม


คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

3

นักพัฒนาและผู้ดูแลระบบที่ใช้ Bash อาจพบว่าฟังก์ชันอำนวยความสะดวกเหล่านี้มีประโยชน์:

jar_jdk_version() {
  [[ -n "$1" && -x "`command -v javap`" ]] && javap -classpath "$1" -verbose $(jar -tf "$1" | grep '.class' | head -n1 | sed -e 's/\.class$//') | grep 'major version' | sed -e 's/[^0-9]\{1,\}//'
}

print_jar_jdk_version() {
  local version
  version=$(jar_jdk_version "$1")
  case $version in 49) version=1.5;; 50) version=1.6;; 51) version=1.7;; 52) version=1.8;; esac
  [[ -n "$version" ]] && echo "`basename "$1"` contains classes compiled with JDK version $version."
}

คุณสามารถวางพวกเขาในเวลาหนึ่งเวลาการใช้งานหรือเพิ่มไปยังหรือ~/.bash_aliases ~/.bashrcผลลัพธ์มีลักษณะดังนี้:

$ jar_jdk_version poi-ooxml-3.5-FINAL.jar
49

และ

$ print_jar_jdk_version poi-ooxml-3.5-FINAL.jar
poi-ooxml-3.5-FINAL.jar contains classes compiled with JDK version 1.5.

แก้ไข ตามที่jackrabbitชี้ให้เห็นคุณไม่สามารถเชื่อถือได้อย่างชัดแจ้ง 100% เพื่อบอกสิ่งที่มีประโยชน์ ถ้าเป็นเช่นนั้นคุณสามารถดึงมันออกมาในเชลล์ UNIX ที่คุณโปรดปรานด้วยunzip:

$ unzip -pa poi-ooxml-3.5-FINAL.jar META-INF/MANIFEST.MF
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 11.3-b02 (Sun Microsystems Inc.)
Built-By: yegor
Specification-Title: Apache POI
Specification-Version: 3.5-FINAL-20090928
Specification-Vendor: Apache
Implementation-Title: Apache POI
Implementation-Version: 3.5-FINAL-20090928
Implementation-Vendor: Apache

. jar นี้ไม่มีประโยชน์ใด ๆ ในรายการที่เกี่ยวข้องกับคลาสที่มีอยู่


คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

3

หนึ่งซับ (Linux)

unzip -p mylib.jar META-INF/MANIFEST.MF

สิ่งนี้จะพิมพ์เนื้อหาของMANIFEST.MFไฟล์ไปยัง stdout (หวังว่าจะมีหนึ่งในไฟล์ jar ของคุณ :)

คุณจะพบรุ่นCreated-ByหรือBuild-Jdkคีย์JDK ทั้งนี้ขึ้นอยู่กับแพคเกจที่สร้างขึ้น


3
โปรดทราบว่าไม่มีข้อผูกมัดใด ๆ สำหรับฟิลด์เหล่านี้ที่จะปรากฏMANIFEST.MFรวมทั้งไม่มีข้อผูกมัดใด ๆ สำหรับค่าที่ถูกต้อง (ใช่ฉันเคยพบ.jarที่ที่ค่านั้นปลอม)
— zb226

คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

2

ไฟล์คลาสแต่ละไฟล์มีหมายเลขเวอร์ชันฝังอยู่สำหรับระดับโค้ดไบต์ซึ่ง JVM ใช้เพื่อดูว่ามันชอบโค้ดไบต์เฉพาะหรือไม่ นี่คือ 48 สำหรับ Java 1.4, 49 สำหรับ Java 1.5 และ 50 สำหรับ Java 6

คอมไพเลอร์จำนวนมากมีอยู่ซึ่งสามารถสร้างรหัสไบต์ในแต่ละระดับ javac ใช้ตัวเลือก "-target" เพื่อระบุระดับรหัสไบต์ที่จะสร้างและ Java 6 javac สามารถสร้างรหัสไบต์อย่างน้อย 1.4, 1.5 และ 6 ฉันไม่ได้ เชื่อว่าคอมไพเลอร์แทรกอะไรก็ได้ที่สามารถระบุคอมไพเลอร์เองซึ่งเป็นสิ่งที่ฉันคิดว่าคุณขอ นอกจากนี้คอมไพเลอร์ Eclipse กำลังถูกใช้มากขึ้นเนื่องจากเป็น jar เดียวที่สามารถรันด้วย JRE เท่านั้น

ในไฟล์ jar มักจะมีหลายคลาสและแต่ละคลาสมีความเป็นอิสระดังนั้นคุณต้องตรวจสอบคลาสทั้งหมดใน jar เพื่อให้แน่ใจเกี่ยวกับลักษณะของเนื้อหา


1

ติดตามคำตอบของ @David J. Liszewski ฉันรันคำสั่งต่อไปนี้เพื่อแยกรายการไฟล์ jar บน Ubuntu:

# Determine the manifest file name:
$ jar tf LuceneSearch.jar | grep -i manifest
META-INF/MANIFEST.MF

# Extract the file:
$ sudo jar xf LuceneSearch.jar META-INF/MANIFEST.MF

# Print the file's contents:
$ more META-INF/MANIFEST.MF
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b30 (Oracle Corporation)
Main-Class: org.wikimedia.lsearch.config.StartupManager

2
หรือเป็นสายการบินunzip -p LiceneSearch.jar META-INF/MANIFEST.MF
— Ogre Psalm33

คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

1

บางครั้งคุณอาจดูไฟล์ jar ทั้งหมดหรือไฟล์ war ที่มีไฟล์ jar จำนวนมากนอกเหนือจากตัวเอง

เนื่องจากฉันไม่ต้องการตรวจสอบแต่ละชั้นฉันจึงเขียนโปรแกรม java เพื่อทำสิ่งนั้น:

https://github.com/Nthalk/WhatJDK

./whatjdk some.war
some.war:WEB-INF/lib/xml-apis-1.4.01.jar contains classes compatible with Java1.1
some.war contains classes compatible with Java1.6

แม้ว่านี่จะไม่ได้บอกว่าคลาสใดที่คอมไพล์ด้วยมันจะกำหนดว่า JDK จะสามารถโหลดคลาสได้อย่างไรซึ่งอาจเป็นสิ่งที่คุณต้องการเริ่มต้นด้วย


1

หากต้องการขยายคำตอบของJonathon FaustและMcDowell : หากคุณใช้ระบบที่ใช้ * nix คุณสามารถใช้od(หนึ่งในโปรแกรม Unix ที่เก่าแก่ที่สุด1ซึ่งควรใช้ได้จริงทุกที่) เพื่อสอบถาม.classไฟล์ในระดับไบนารี:

od -An -j7 -N1 -t dC SomeClassFile.class

สิ่งนี้จะส่งออกค่าจำนวนเต็มที่คุ้นเคยเช่น50for Java 5, 51for Java 6และอื่น ๆ

1อ้างจากhttps://en.wikipedia.org/wiki/Od_(Unix)


คำสั่งเหล่านี้ส่งมอบเวอร์ชัน JVM เป้าหมายไม่ใช่javacเวอร์ชันที่รวบรวมไฟล์. class ซึ่งเป็นสิ่งที่ถูกถาม
— มาร์ควิสแห่ง Lorne

1

ฉันก็เขียนสคริปต์ทุบตีของฉันเองเพื่อทิ้งรุ่น Java ที่ต้องการโดยไหทั้งหมดที่ส่งผ่านบรรทัดคำสั่ง ... Mine ค่อนข้างหยาบ แต่ใช้ได้สำหรับฉัน ;-)

ตัวอย่างการใช้งาน

$ jar_dump_version_of_jvm_required.sh *.jar
JVM VERSION REQUIRED: 46.0, /private/tmp/jars/WEB-INF/lib/json-simple-1.1.jar
JVM VERSION REQUIRED: 49.0, /private/tmp/jars/WEB-INF/lib/json-smart-1.1.1.jar
JVM VERSION REQUIRED: 50.0, /private/tmp/jars/WEB-INF/lib/jsontoken-1.0.jar
JVM VERSION REQUIRED: 50.0, /private/tmp/jars/WEB-INF/lib/jsr166y-1.7.0.jar

jar_dump_version_of_jvm_required.sh

#!/bin/bash

DIR=$(PWD)
function show_help()
{
  ME=$(basename $0)
  IT=$(cat <<EOF

  Dumps the version of the JVM required to run the classes in a jar file

  usage: $ME JAR_FILE

  e.g. 

  $ME myFile.jar    ->  VERSION: 50.0     myFile.jar

  Java versions are:
  54 = Java 10
  53 = Java 9
  52 = Java 8
  51 = Java 7
  50 = Java 6
  49 = Java 5
  48 = Java 1.4
  47 = Java 1.3
  46 = Java 1.2
  45.3 = Java 1.1

EOF
  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

function unzipJarToTmp()
{
  JAR=$1
  CLASS_FILE=$(jar -tf "$JAR" | grep \.class$ | grep -v '\$' | head -n1 | awk '{print $NF}')
  OUT_FILE="$CLASS_FILE"
  #echo "J=$JAR C=$CLASS_FILE O=$OUT_FILE"
  jar xf "$JAR" "$CLASS_FILE"

  MAJOR=$(javap -v "$OUT_FILE" 2>&1 | grep major | awk -F' ' '{print $3'})
  MINOR=$(javap -v "$OUT_FILE" 2>&1 | grep minor | awk -F' ' '{print $3'})
  if [ -z "$MAJOR" ]
  then
    echo "JVM VERSION REQUIRED: NA as no classes in $JAR"
  else
    echo "JVM VERSION REQUIRED: $MAJOR.$MINOR, $JAR"
  fi
}

# loop over cmd line args
for JAR in "$@"
do
  cd "$DIR"
  JAR_UID=$(basename "$JAR" | sed s/.jar//g)
  TMPDIR=/tmp/jar_dump/$JAR_UID/
  mkdir -p "$TMPDIR"
  JAR_ABS_PATH=$(realpath $JAR)

  cd "$TMPDIR"

  #echo "$JAR_ABS_PATH"
  unzipJarToTmp "$JAR_ABS_PATH"
  #sleep 2
done

1

คุณสามารถทำสิ่งนี้บนบรรทัดรับคำสั่งโดยใช้กระบวนการต่อไปนี้:

หากคุณรู้จักชื่อคลาสใด ๆ ใน jar คุณสามารถใช้คำสั่งต่อไปนี้:

javap -cp jarname.jar -verbose packagename.classname | findstr major

ตัวอย่าง:

    C:\pathwherejarlocated> javap -cp jackson-databind-2.8.6.jar -verbose com.fasterxml.jackson.databind.JsonMappingException | findstr major

ผลผลิต:

    major version: 51

อ้างอิงด่วน:

JDK 1.0 — major version 45 
DK 1.1 — major version 45 
JDK 1.2 — major version 46 
JDK 1.3 — major version 47 
JDK 1.4 — major version 48 
JDK 1.5 — major version 49 
JDK 1.6 — major version 50 
JDK 1.7 — major version 51 
JDK 1.8 — major version 52 
JDK 1.9 — major version 53 

PS: ถ้าคุณไม่รู้จักชื่อ class คุณสามารถทำได้โดยใช้ decompilers jar หรือเพียงแค่ใช้คำสั่งต่อไปนี้เพื่อแตกไฟล์ jar:

jar xf myFile.jar


-1

บน Windows ให้ทำสิ่งต่อไปนี้:

  1. คลายซิปหรือแตกไฟล์ JAR โดยใช้คำสั่ง WinZip / Java JAR
  2. ลากและวางไฟล์คลาสหนึ่งในโครงการ Eclipse Java ของคุณ
  3. เปิดไฟล์คลาส

ตอนนี้ Eclipse จะแสดงเวอร์ชันหลักและเวอร์ชันรองแน่นอน


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.