জাভা। ক্লাস সংস্করণগুলি পড়ার এবং প্রদর্শন করার সরঞ্জাম


115

আপনারা কেউ এমন কোনও সরঞ্জাম সম্পর্কে জানেন যা .class ফাইলগুলি অনুসন্ধান করবে এবং তারপরে সংকলিত সংস্করণগুলি প্রদর্শন করবে?

আমি জানি যে আপনি হেক্স সম্পাদকের মধ্যে স্বতন্ত্রভাবে সেগুলি দেখতে পারেন তবে আমার কাছে দেখতে অনেকগুলি ক্লাস ফাইল রয়েছে (আমার দৈত্য অ্যাপ্লিকেশনটিতে কিছু কারণে জাভা 6 সংকলন করছে)।


1
আরও জনপ্রিয় ডুপ্লিকেট স্ট্যাকওভারফ্লো.com/ প্রশ্নগুলি ১০০৯6১৪৮/২ এর উত্তর রয়েছে এখানে কিছু উল্লেখযোগ্য সরঞ্জাম নেই।
ভাদজিম

উত্তর:


142

JDK এর সাথে আসা জাভাপ সরঞ্জামটি ব্যবহার করুন । -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

ক্লাস ফাইলের স্বাক্ষরটি পড়া এবং তৃতীয় পক্ষের এপিআই ছাড়াই এই মানগুলি পাওয়া যথেষ্ট সহজ । আপনাকে কেবল প্রথম 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);
    }
  }
}

হাঁটার ডিরেক্টরি ( ফাইল ) এবং সংরক্ষণাগার ( জারফাইল )ক্লাস ফাইলগুলির জন্য ) তুচ্ছ।

ওরাকল এর জো ডার্সির ব্লগটি জাভা 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

এছাড়াও মনে রাখবেন যে জাভা চালু করার সময় এটি সক্ষম থাকলেই এটি চালানো হয় যাতে আপনি জাঙ্ক ফাইলগুলি পড়তে পারেন যদি আপনি অবৈধআর্গুমেন্টএক্সেপশন (উদাহরণস্বরূপ) ব্যবহার না করেন
jontejj

21

ইউনিক্স-মত

ফাইল / পাথ / টু / থিংক্লস

ফাইল টাইপ এবং সংস্করণ পাশাপাশি দেবে। আউটপুটটি দেখতে কেমন দেখাচ্ছে তা এখানে:

সংকলিত জাভা বর্গ তথ্য, সংস্করণ 49.0


(থেকে WMR এর উত্তর সরলীকৃত)
phunehehe

এটি অন্য সমাধানগুলির চেয়ে সহজতর
মিমুলার

9

আপনি যদি কোনও ইউনিক্স সিস্টেমে থাকেন তবে আপনি কেবল একটি করতে পারেন

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

(ফাইলের আমার সংস্করণটি জাভা classes টি ক্লাসের জন্য "সংকলিত জাভা শ্রেণীর ডেটা, সংস্করণ ৫০.০" বলে)


ম্যাকোজে (কমপক্ষে 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

গ্রহনে আপনার যদি সংযুক্ত উত্স না থাকে। সংযুক্ত উত্স বোতামের পরে প্রথম লাইনটি মনে রাখুন।

// সিডিস্টিনোলগ.জভা থেকে সংকলিত ( সংস্করণ 1.5: 49.0, সুপার বিট )

এখানে চিত্র বর্ণনা লিখুন


2

হতে পারে এটি কাউকেও সহায়তা করে। মনে হচ্ছে জাভা সংস্করণ .class সংকলন / তৈরি করতে আরও সহজ উপায় পাওয়া যায়। এই উপায়টি জাভা ভার্সনে অ্যাপ্লিকেশন / শ্রেণির স্বতঃপরীক্ষণে কার্যকর।

আমি জেডিকে লাইব্রেরি পেরিয়ে এই দরকারী ধ্রুবকটি পেয়েছি: com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION । জাভা জেডিকে কখন থেকে তা জানি না।

কোডটির এই টুকরোটি বেশ কয়েকটি সংস্করণ ধ্রুবকগুলির জন্য চেষ্টা করে নীচে ফলাফল পেয়েছি:

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

ক্লাস বাইটকোডে সত্যিই ধ্রুবক রয়েছে - মেইনক্যাল এর লাল চিহ্নিত অংশ দেখুন - ক্লাস বাইটকোডে ধ্রুবক সঞ্চিত

যদি জাভা সংস্করণ তারিখ সীমার বাইরে স্থায়ী পরীক্ষণের জন্য নাও ব্যবহৃত বর্গ হয় (দেখুন কিভাবে জাভা চেক তারিখ সীমার বাইরে যে ) ...


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

এই জাভা বর্গ ডিরেক্টরিগুলির তালিকার নীচে পাওয়া সমস্ত ওয়ারের সামগ্রী এবং জেআর এর সামগ্রীগুলি স্ক্যান করে এবং প্রতিটি উপাদানগুলির জন্য জাভা বর্গ ফাইল সংস্করণের সংক্ষিপ্তসারগুলি ওয়ার্সের মধ্যে প্রতিটি জেআর অন্তর্ভুক্ত করে:

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);
            }
        };
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.