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.