어떤 버전의 자바크가 내 항아리를 만들었지?
자바 컴파일러의 어떤 버전을 사용하여 jar를 작성했는지 어떻게 알 수 있습니까?jar 파일이 있는데, 3개의 JDK 중 하나에 구축되어 있을 수 있습니다.호환성을 인정하기 위해서는 어느 것이 정확한지 알아야 합니다.컴파일러 버전이 클래스 파일 또는 jar 어딘가에 포함되어 있습니까?
A jar
단순한 용기일 뿐입니다.파일 아카이브입니다.한편,jar
META-INF 계층 내에 흥미로운 정보가 포함되어 있을 수 있으므로 콘텐츠 내에서 클래스의 빈티지를 지정할 의무는 없습니다.그러기 위해서는 다음 사항을 검토해야 합니다.class
파일을 첨부합니다.
Peter Lawrey가 첫 번째 질문에서 언급했듯이, 어떤 JDK 릴리스가 특정 시스템을 구축했는지 반드시 알 수는 없습니다.class
에서는 바이트 할 수 .class
jar
.
좀 , 첫 번째 는 하나 를 ,, from, from, , 좀에서 추출하는 입니다.jar
§:
$ jar xf log4j-1.2.15.jar
Cygwin이 설치된 Linux, Mac OS X 또는 Windows에서는 file(1) 명령어로 클래스 버전을 알 수 있습니다.
$ file ./org/apache/log4j/Appender.class
./org/apache/log4j/Appender.class: compiled Java class data, version 45.3
는,를 사용하여javap
JDK @jikes @과 같이합니다.선더볼트
$ 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
WWIW, WWIW, WWIW에 합니다.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
- 54 = Java 10
- 55 = Java 11
- 56 = Java 12
- 57 = Java 13
- 58 = Java 14
JAR 파일만으로는 알 수 없습니다.
16진수 에디터를 다운로드하여 JAR 내의 클래스 파일 중 하나를 열고 바이트 오프셋 4 ~7을 확인합니다.버전 정보가 포함되어 있습니다.
http://en.wikipedia.org/wiki/Java_class_file
주의: 아래 코멘트에 기재되어 있는 바와 같이
이 바이트는 클래스가 컴파일된 버전이 아니라 컴파일된 버전의 클래스를 알려 줍니다.
이 정보를 찾는 Java의 방법은 다음과 같습니다.
Windows:javap -v <class> | findstr major
Unix:javap -v <class> | grep major
예를 들어 다음과 같습니다.
> javap -v Application | findstr major major version: 51
Windows 에서는, JAR 를 언팩 할 필요가 없습니다(클래스명 중 하나가 알려져 있거나, 7zip 를 사용해 검색되고 있는 경우 등).이것으로 충분합니다.
javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major
컴파일러Java 컴파일러)(javac
jar를 파일로 는 jar를 빌드하지 않고 Java 파일을 클래스 파일로 변환합니다. 툴Jar ()jar
에 의해 생성됩니다는 실제 병을 만듭니다.커스텀 매니페스트를 지정하지 않은 경우 기본 매니페스트는 jar 작성에 사용된 JDK 버전을 지정합니다.
뚱뚱한 항아리를 분석해야 했기 때문에 항아리 파일의 각 클래스 버전에 관심이 있었습니다.따라서 저는 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 스크립트 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
Hex Editor를 사용하여 .class 파일에서 Java 컴파일러 버전을 찾을 수 있습니다.
순서 1: zip 압축 해제기를 사용하여 jar 파일에서 .class 파일을 추출합니다.
스텝 2: .class 파일을 16진 에디터로 엽니다.(메모장++ 16진 에디터 플러그인을 사용하고 있습니다.이 플러그인은 파일을 바이너리로 읽고 16진수로 표시합니다.아래를 참조해 주십시오.
인덱스 6과 7은 사용되는 클래스 파일 형식의 메이저버전 번호를 나타냅니다.https://en.wikipedia.org/wiki/Java_class_file
Java SE 11 = 55 (0x37 16진수)
Java SE 10 = 54 (0x36 16진수)
Java SE 9 = 53 (0x35 16진수)
Java SE 8 = 52 (0x34 16진수),
Java SE 7 = 51 (0x33 16진수),
Java SE 6.0 = 50 (0x32 16진수),
Java SE 5.0 = 49 (0x31 16진수),
JDK 1.4 = 48 (0x30 16진수),
JDK 1.3 = 47(0x2F 16진수),
JDK 1.2 = 46 (0x2E 16진수),
JDK 1.1 = 45 (0x2D 16진수).
Java 바이너리 버전은 처음 8바이트를 검사하여 알 수 있습니다(또는 가능한 앱을 사용하여 알 수 있습니다.
컴파일러 자체는 식별 가능한 서명을 삽입하지 않습니다.VM 사양 클래스 형식의 파일에서는 이러한 파일을 찾을 수 없습니다.
Owen이 게시한 코드를 통해 다른 답변이 언급한 정보를 알 수 있습니다.
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
}
}
이것과 이 사이트를 참조해 주세요.결국 마인드 프로덕트 코드를 빠르게 수정하여 각각의 의존관계가 무엇 때문에 컴파일되었는지 확인하게 되었습니다.
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.
편집 잭 래빗이 지적한 바와 같이, 당신은 당신에게 유용한 것을 알려주기 위해 매니페스트에 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에는 포함된 클래스에 대한 유용한 정보가 없습니다.
라이너 1개(Linux)
unzip -p mylib.jar META-INF/MANIFEST.MF
'하다'의 됩니다.MANIFEST.MF
to ( ) stdout ( jar " 1 " 1 " ) : )
, 은 「JDK」에 .Created-By
★★★★★★★★★★★★★★★★★」Build-Jdk
를 누릅니다
각 클래스 파일에는 바이트 코드레벨에 대한 버전 번호가 포함되어 있습니다.이 버전 번호는 JVM이 특정 바이트 코드 청크를 좋아하는지 여부를 확인하기 위해 사용합니다.이것은 Java 1.4의 경우 48, Java 1.5의 경우 49, Java 6의 경우 50입니다.
각 레벨에서 바이트 코드를 생성할 수 있는 컴파일러가 다수 존재합니다.javac은 "-target" 옵션을 사용하여 생성할 바이트 코드 수준을 나타내며 Java 6 javac은 최소 1.4, 1.5 및 6의 바이트 코드를 생성할 수 있습니다.컴파일러가 컴파일러 자체를 식별할 수 있는 것을 삽입할 수 있다고는 생각하지 않습니다.또한 이클립스 컴파일러는 JRE에서만 실행할 수 있는 단일 jar이기 때문에 점점 더 많이 사용되고 있습니다.
jar 파일에는 보통 많은 클래스가 있으며 각각 독립적이기 때문에 내용의 특성을 확인하기 위해 jar 내의 모든 클래스를 조사해야 합니다.
대부분의 경우 전체 jar 파일 또는 jar 파일 외에도 많은 jar 파일이 포함된 전쟁 파일을 볼 수 있습니다.
각 수업을 손으로 체크하고 싶지 않았기 때문에 이를 위해 자바 프로그램을 작성했습니다.
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가 클래스를 로드할 수 있는지 결정합니다.이것이 아마 처음에 의도한 것일 것입니다.
이 작업은 명령줄에서 다음 프로세스를 사용하여 쉽게 수행할 수 있습니다.
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 : 클래스 이름을 모르는 경우 jar 디컴파일러 중 하나를 사용하거나 다음 명령어를 사용하여 jar 파일을 추출하는 것만으로 쉽게 할 수 있습니다.
jar xf myFile.jar
IntelliJ 사용자
- 플러그인 아카이브 브라우저 설치

인텔리에서 항아리를 엽니다.파일 브라우저에서 jar 파일을 드래그 앤 드롭하여 프로젝트에 jar를 추가할 수 있습니다.
jar 파일을 참조하여 클래스 파일을 찾습니다.인텔리J의 디컴파일러는 jar 작성에 사용된 Java 버전을 표시합니다.
@David J. Liszewski의 답변에 따라 다음 명령을 실행하여 Ubuntu에서 jar 파일의 매니페스트를 추출했습니다.
# 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
Jonathon Faust와 McDowell의 답변을 자세히 설명하겠습니다.*nix 기반 시스템을 사용하는 경우od
(실제로 어디에서나 이용 가능해야 하는 최초의 Unix1 프로그램 중 하나)를 사용하여.class
이진 수준에서의 파일:
od -An -j7 -N1 -t dC SomeClassFile.class
그러면 익숙한 정수 값이 출력됩니다.50
위해서Java 5
,51
위해서Java 6
기타 등등.
1 https://en.wikipedia.org/wiki/Od_(Unix)에서 인용
명령줄에 전달된 모든 jars에 필요한 Java 버전을 덤프하기 위해 bash 스크립트를 직접 작성했습니다.저는 조금 거칠지만, 저는 괜찮습니다;-)
사용 예
$ 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_syslog_version_of_jvm_required 입니다.쉿
#!/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
jar 예제의 Manifest 파일을 체크인합니다.
매니페스트 버전: 1.0 작성 기준: 1.6.0 (IBM Corporation)
Windows 의 경우는, 다음의 순서에 따릅니다.
- WinZip / Java JAR 명령을 사용하여 JAR 파일을 압축 해제하거나 압축을 풉니다.
- 클래스 파일 중 하나를 Eclipse Java 프로젝트에 끌어다 놓습니다.
- 클래스 파일을 엽니다.
이제 이클립스는 정확한 메이저 버전과 마이너 버전을 보여줄 것입니다.
(github에서) Davids의 제안에 따라 bash 스크립트를 작성합니다.file
명령어
언급URL : https://stackoverflow.com/questions/3313532/what-version-of-javac-built-my-jar
'programing' 카테고리의 다른 글
페이지를 변경할 때 Nuxt JS 페이지 컨텐츠가 깜박입니다. (0) | 2022.08.31 |
---|---|
Java 컬렉션을 올바르게 인쇄(toString이 예쁜 출력을 반환하지 않음) (0) | 2022.08.31 |
VueX 변환은 작동하지만 구성 요소 계산 속성이 작동하지 않음 (0) | 2022.08.31 |
간단한 Linux 디바이스 드라이버 작성 방법 (0) | 2022.08.31 |
재사용 가능한 컴포넌트가 있는 라우터 뷰에서는 Vue 전환이 기능하지 않음 (0) | 2022.08.31 |