जावा .class संस्करणों को पढ़ने और प्रदर्शित करने के लिए उपकरण


115

क्या आप में से कोई एक उपकरण जानता है जो .class फ़ाइलों की खोज करेगा और फिर उनके संकलित संस्करण प्रदर्शित करेगा?

मुझे पता है कि आप उन्हें एक हेक्स संपादक में व्यक्तिगत रूप से देख सकते हैं लेकिन मेरे पास देखने के लिए बहुत सारी क्लास फाइलें हैं (मेरे विशाल आवेदन में कुछ किसी कारण से जावा 6 के लिए संकलन है)।


1
अधिक लोकप्रिय डुप्लिकेट stackoverflow.com/questions/1096148/… में उत्तर दिया गया है कि कुछ उपयोगी उपकरण यहाँ नहीं हैं।
वडज़िम

जवाबों:


142

JDK के साथ आने वाले javap टूल का उपयोग करें । -verboseविकल्प वर्ग फ़ाइल की संस्करण संख्या प्रिंट होगा।

> javap -verbose MyClass
Compiled from "MyClass.java"
public class MyClass
  SourceFile: "MyClass.java"
  minor version: 0
  major version: 46
...

केवल संस्करण दिखाने के लिए:

WINDOWS> javap -verbose MyClass | find "version"
LINUX  > javap -verbose MyClass | grep version

2
संस्करण प्रमुख.मिनोर = जेडीके / जावाएसई; 45.3 = JDK1.1; 46.0 = JDK1.2; 47.0 = JDK1.3; 48.0 = JDK1.4; 49.0 = JavaSE5 (1.5); 51.0 = JavaSE7 (1.7); 50.0 = JavaSE6 (1.6); 52.0 = JavaSE8 (1.8); 53.0 = JavaSE9; 54.0 = JavaSE10; 55.0 = JavaSE11; 56.0 = JavaSE12; 57.0 = JavaSE13; 58.0 = JavaSE14;
भतीजे

45

कक्षा फ़ाइल हस्ताक्षर को पढ़ना और 3 जी एपीआई के बिना इन मूल्यों को प्राप्त करना काफी आसान है । आपको बस पहले 8 बाइट्स पढ़ने की ज़रूरत है।

ClassFile {
    u4 magic;
    u2 minor_version;
    u2 major_version;

कक्षा फ़ाइल संस्करण 51.0 (जावा 7) के लिए, उद्घाटन बाइट्स हैं:

CA FE BA BE 00 00 00 33

... जहां 0xCAFEBABE मैजिक बाइट्स हैं, 0x0000 मामूली संस्करण है और 0x0033 प्रमुख संस्करण है।

import java.io.*;

public class Demo {
  public static void main(String[] args) throws IOException {
    ClassLoader loader = Demo.class.getClassLoader();
    try (InputStream in = loader.getResourceAsStream("Demo.class");
        DataInputStream data = new DataInputStream(in)) {
      if (0xCAFEBABE != data.readInt()) {
        throw new IOException("invalid header");
      }
      int minor = data.readUnsignedShort();
      int major = data.readUnsignedShort();
      System.out.println(major + "." + minor);
    }
  }
}

चलना निर्देशिका ( फ़ाइल ) और अभिलेखागार ( JarFile ) वर्ग फ़ाइलों की तलाश में तुच्छ है।

ओरेकल के जो डार्सी के ब्लॉग ने जेडीके संस्करण के वर्ग संस्करण को जावा 7 तक मैपिंग में सूचीबद्ध किया है :

Target   Major.minor Hex
1.1      45.3        0x2D
1.2      46.0        0x2E
1.3      47.0        0x2F
1.4      48.0        0x30
5 (1.5)  49.0        0x31
6 (1.6)  50.0        0x32
7 (1.7)  51.0        0x33
8 (1.8)  52.0        0x34
9        53.0        0x35

यह भी याद रखें कि एस्टर केवल तभी चलाया जाता है यदि यह जावा लॉन्च करते समय सक्षम हो, ताकि आप जंक फ़ाइलों को पढ़ सकें यदि आप IllegalArgumentException (उदाहरण के लिए) का उपयोग नहीं कर रहे हैं
jontejj

21

यूनिक्स की तरह

file /path/to/Thing.class

फ़ाइल प्रकार और संस्करण भी देंगे। यहाँ वही है जो आउटपुट दिखता है:

संकलित जावा वर्ग डेटा, संस्करण 49.0



यह अन्य समाधानों की तुलना में अधिक सरल है
mmuller

9

यदि आप एक यूनिक्स प्रणाली पर हैं तो आप बस एक कर सकते हैं

find /target-folder -name \*.class | xargs file | grep "version 50\.0"

(मेरी फ़ाइल का संस्करण java6 कक्षाओं के लिए "संकलित जावा क्लास डेटा, संस्करण 50.0" कहता है)।


MacOS पर (10.12.6 कम से कम), आउटपुट और भी अधिक उपयोगी है: file *.class उत्पादन: ClassName.class: compiled Java class data, version 50.0 (Java 1.6)
गैरी

5

फिर भी एक और जावा संस्करण की जाँच करें

od -t d -j 7 -N 1 ApplicationContextProvider.class | head -1 | awk '{print "Java", $2 - 44}'

5

यदि आपके पास स्रोत संलग्न नहीं हैं तो ग्रहण में। अटैच सोर्स बटन के बाद पहली लाइन को माइंड करें।

// CDestinoLog.java से संकलित ( संस्करण 1.5: 49.0, सुपर बिट )

यहां छवि विवरण दर्ज करें


2

शायद इससे किसी की मदद भी हो जाए। लगता है कि JAVA संस्करण को संकलन / निर्माण के लिए उपयोग करने के लिए और अधिक आसान तरीका है। यह तरीका JAVA संस्करण पर एप्लिकेशन / क्लास सेल्फ चेक के लिए उपयोगी है।

मैं JDK लाइब्रेरी से गुजरा हूँ और इस उपयोगी स्थिरांक को पाया है: com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION । मुझे नहीं पता कि यह कब से JAVA JDK में है।

कई संस्करण स्थिरांक के लिए इस कोड के टुकड़े की कोशिश करने से मुझे नीचे परिणाम मिलेगा:

src:

System.out.println("JAVA DEV       ver.: " + com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION);
System.out.println("JAVA RUN     v. X.Y: " + System.getProperty("java.specification.version") );
System.out.println("JAVA RUN v. W.X.Y.Z: " + com.sun.deploy.config.Config.getJavaVersion() ); //_javaVersionProperty
System.out.println("JAVA RUN  full ver.: " + System.getProperty("java.runtime.version")  + " (may return unknown)" );
System.out.println("JAVA RUN       type: " + com.sun.deploy.config.Config.getJavaRuntimeNameProperty() );

उत्पादन:

JAVA DEV       ver.: 1.8.0_77
JAVA RUN     v. X.Y: 1.8
JAVA RUN v. W.X.Y.Z: 1.8.0_91
JAVA RUN  full ver.: 1.8.0_91-b14 (may return unknown)
JAVA RUN       type: Java(TM) SE Runtime Environment

क्लास बायटेकोड में वास्तव में स्थिर संग्रहीत होता है - मेन.कॉल का लाल चिह्नित हिस्सा देखें - लगातार .class bytecode में संग्रहीत

कॉन्स्टेंट वर्ग में जाँच के लिए उपयोग किया जाता है यदि जावा संस्करण पुराना हो गया है (देखें कि जावा कैसे चेक आउट हो चुका है ) ...


1

संस्करण जादू संख्याओं का उपयोग करके एक जावा-आधारित समाधान । नीचे इसका उपयोग प्रोग्राम द्वारा स्वयं इसके बाइटकोड संस्करण का पता लगाने के लिए किया जाता है।

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
public class Main {
    public static void main(String[] args) throws DecoderException, IOException {
        Class clazz = Main.class;
        Map<String,String> versionMapping = new HashMap();
        versionMapping.put("002D","1.1");
        versionMapping.put("002E","1.2");
        versionMapping.put("002F","1.3");
        versionMapping.put("0030","1.4");
        versionMapping.put("0031","5.0");
        versionMapping.put("0032","6.0");
        versionMapping.put("0033","7");
        versionMapping.put("0034","8");
        versionMapping.put("0035","9");
        versionMapping.put("0036","10");
        versionMapping.put("0037","11");
        versionMapping.put("0038","12");
        versionMapping.put("0039","13");
        versionMapping.put("003A","14");

        InputStream stream = clazz.getClassLoader()
            .getResourceAsStream(clazz.getName().replace(".", "/") + ".class");
        byte[] classBytes = IOUtils.toByteArray(stream);
        String versionInHexString = 
            Hex.encodeHexString(new byte[]{classBytes[6],classBytes[7]});
        System.out.println("bytecode version: "+versionMapping.get(versionInHexString));
    }
}

0

यह जावा वर्ग सभी WAR सामग्री और JAR की सामग्री को निर्देशिकाओं की सूची के तहत स्कैन करता है, और प्रत्येक घटक के लिए जावा वर्ग फ़ाइल संस्करणों का सारांश WARs के भीतर प्रत्येक JAR शामिल करता है:

public class ShowClassVersions {
    private static final byte[] CLASS_MAGIC = new byte[] {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe};
    private final byte[] bytes = new byte[8];
    private TreeMap<String,ArrayList<String>> vers = new TreeMap<>();

    private void scan(Path f) throws IOException {
        if (Files.isDirectory(f)) {
            Pattern pattern = Pattern.compile("\\.[wj]ar$"); // or |\\.class
            try(var stream = Files.find(f, Integer.MAX_VALUE, (p,a) -> a.isRegularFile() && pattern.matcher(p.toString()).find())) {
                stream.forEach(this::scanFile);
            }
            return;
        }
        scanFile(f);
    }
    private void scanFile(Path f) {
        String fn = f.getFileName().toString();
        try {
            if (fn.endsWith(".jar"))
                scanArchive(f);
            else if (fn.endsWith(".war"))
                scanArchive(f);
            else if (fn.endsWith(".class"))
                record(f, versionOfClass(f));
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
    private void scanArchive(Path p) throws IOException {
        try(InputStream in = Files.newInputStream(p))  {
            scanArchive(p.toAbsolutePath().toString(), in);
        }
    }
    private String scanArchive(String desc, InputStream in) throws IOException {
        String version = null;
        ZipInputStream zip = new ZipInputStream(in);
        ZipEntry entry = null;
        while ((entry = zip.getNextEntry()) != null) {
            String name = entry.getName();
            if (version == null && name.endsWith(".class"))  {
                version = versionOfClass(zip);
            }
            else if (name.endsWith(".jar"))  {
                scanArchive(desc+" ==>> "+name, zip);
            }
        }
        if (version != null)
            record(desc, version);
        return version;
    }

    private String versionOfClass(Path p) throws IOException {
        String version = null;
        try(InputStream in = Files.newInputStream(p)) {
            version = versionOfClass(in);
        }
        return version;
    }

    private String versionOfClass(InputStream in) throws IOException {
        String version = null;
        int c = in.read(bytes);
        if (c == bytes.length && Arrays.mismatch(bytes, CLASS_MAGIC) == CLASS_MAGIC.length) {
            int minorVersion = (bytes[4] << 8) + (bytes[4] << 0);
            int majorVersion = (bytes[6] << 8) + (bytes[7] << 0);
            version = ""+majorVersion + "." + minorVersion;
        }
        return version;
    }
    private void record(String p, String v) {
        vers.computeIfAbsent(String.valueOf(v), k -> new ArrayList<String>()).add(p);
    }
    private void record(Path p, String v) {
        record(p.toAbsolutePath().toString(), v);
    }
    public static void main(String[] args) throws IOException {
        ShowClassVersions v = new ShowClassVersions();
        var files = Arrays.stream(args).map(Path::of).collect(Collectors.toList());
        for (var f : files) {
            v.scan(f);
        }
        for (var ver : v.vers.keySet()) {
            System.out.println("Version: "+ver);
            for (var p : v.vers.get(ver)) {
                System.out.println("   "+p);
            }
        };
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.