কোন JAR ফাইলটি কোন ক্লাস থেকে এসেছে তা নির্ধারণ করুন


154

আমি এই মুহুর্তে কোনও আইডিইয়ের সামনে নেই, কেবলমাত্র এপিআই স্পেসগুলি দেখছি।

CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
    URL jar = src.getLocation();
}

আমি নির্ধারণ করতে চাই যে কোন জেআর ফাইলটি ক্লাস থেকে এসেছে। এটা কি এই উপায়?


2
কনসোল থেকে এটি করার কোনও উপায় আছে? এরকম কিছু java -findjar -cp /some/path/with/libs/*.jar my.java.Class-> my.jar
kub1x

উত্তর:


191

হ্যাঁ. এটি বুটস্ট্র্যাপ শ্রেণিবদ্ধকারী দ্বারা লোড হওয়া ক্লাস বাদে সমস্ত শ্রেণীর জন্য কাজ করে। নির্ধারণের অন্য উপায়টি হ'ল:

Class klass = String.class;
URL location = klass.getResource('/' + klass.getName().replace('.', '/') + ".class");

নোটনুপ নির্দেশিত klass.getResource()পদ্ধতিটি ক্লাস ফাইলের অবস্থান নিজেই দেয়। উদাহরণ স্বরূপ:

jar:file:/jdk/jre/lib/rt.jar!/java/lang/String.class
file:/projects/classes/pkg/MyClass$1.class

getProtectionDomain().getCodeSource().getLocation()পদ্ধতি বয়াম ফাইল বা CLASSPATH অবস্থান ফেরৎ

file:/Users/home/java/libs/ejb3-persistence-1.0.2.GA.jar
file:/projects/classes

এটি অনুমানগুলি ক্লাসের নাম থেকে ক্লাস ফাইলে ম্যাপিং বন্ধ করে দেয়। এটি বেনাম শ্রেণীর জন্য সঠিকভাবে কাজ করবে? নেস্টেড ক্লাস?
থোরবজর্ন রাভন অ্যান্ডারসন

1
এটি ক্লাসের ইউআরএলকে নির্দেশ করে যা জার নিজেই নয়। জার ফাইলটি খুঁজে পেতে ইউআরএলকে বিশ্লেষণ করা দরকার।
নোট করুন

@notnoop। আমি উত্তরটি পরিষ্কার করে দিয়েছি।
চন্দ্র পাটনি

19
উত্তরে যেমনটি লেখা হয়েছে ঠিক তেমনই এটি অন্যভাবে, getProtectionDomain().getCodeSource().getLocation()আপনি জার-ফাইলের অবস্থান পেতে চাইলে ব্যবহার করুন
পিটার

এই উত্তরের জন্য ধন্যবাদ, এটি আমাকে এই প্রশ্নের উত্তর দিতে অনুপ্রাণিত করেছিল ।
kriegaex

12

লম্বোক প্যাচারLiveInjector.findPathJar() থেকে চেকআউট করুন । দ্রষ্টব্য যে এটি বিশেষ ক্ষেত্রে যেখানে ফাইলটি আসলে জারে থাকে না এবং আপনি এটি পরিবর্তন করতে চাইতে পারেন।LiveInjector.java

/**
 * If the provided class has been loaded from a jar file that is on the local file system, will find the absolute path to that jar file.
 * 
 * @param context The jar file that contained the class file that represents this class will be found. Specify {@code null} to let {@code LiveInjector}
 *                find its own jar.
 * @throws IllegalStateException If the specified class was loaded from a directory or in some other way (such as via HTTP, from a database, or some
 *                               other custom classloading device).
 */
public static String findPathJar(Class<?> context) throws IllegalStateException {
    if (context == null) context = LiveInjector.class;
    String rawName = context.getName();
    String classFileName;
    /* rawName is something like package.name.ContainingClass$ClassName. We need to turn this into ContainingClass$ClassName.class. */ {
        int idx = rawName.lastIndexOf('.');
        classFileName = (idx == -1 ? rawName : rawName.substring(idx+1)) + ".class";
    }

    String uri = context.getResource(classFileName).toString();
    if (uri.startsWith("file:")) throw new IllegalStateException("This class has been loaded from a directory and not from a jar file.");
    if (!uri.startsWith("jar:file:")) {
        int idx = uri.indexOf(':');
        String protocol = idx == -1 ? "(unknown)" : uri.substring(0, idx);
        throw new IllegalStateException("This class has been loaded remotely via the " + protocol +
                " protocol. Only loading from a jar on the local file system is supported.");
    }

    int idx = uri.indexOf('!');
    //As far as I know, the if statement below can't ever trigger, so it's more of a sanity check thing.
    if (idx == -1) throw new IllegalStateException("You appear to have loaded this class from a local jar file, but I can't make sense of the URL!");

    try {
        String fileName = URLDecoder.decode(uri.substring("jar:file:".length(), idx), Charset.defaultCharset().name());
        return new File(fileName).getAbsolutePath();
    } catch (UnsupportedEncodingException e) {
        throw new InternalError("default charset doesn't exist. Your VM is borked.");
    }
}

2
এটি খুব সাধারণ কিছু পাওয়ার জন্য অতিরিক্ত জটিল বলে মনে হচ্ছে। আমি কেবল বসে বসে যা দেখেছি তা চেষ্টা করে দেখেছি এবং এটি কাজ করে। শুধু কিছু বৈধতা চেয়েছিলেন।

আমরা হব. আপনার কোড বুটক্লাস পাথগুলিতে ফাইলগুলি পরিচালনা করে না এবং চন্দ্রের সমাধানটি জার ফাইলটি নয় এমন ফাইলটিতে url ফেরত দেয়, তাই জার ফাইলটি সন্ধানের জন্য আপনাকে পথটি বিশ্লেষণ করতে হবে।
নোট করুন

2

ব্যবহার

String path = <Any of your class within the jar>.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 

এটিতে যদি একাধিক এন্ট্রি থাকে তবে কিছু স্ট্রস্ট্রিং অপারেশন করুন।


1
private String resourceLookup(String lookupResourceName) {



    try {

        if (lookupResourceName == null || lookupResourceName.length()==0) {
            return "";
        }
        // "/java/lang/String.class"

        // Check if entered data was in java class name format
        if (lookupResourceName.indexOf("/")==-1) {
            lookupResourceName = lookupResourceName.replaceAll("[.]", "/");
            lookupResourceName =  "/" + lookupResourceName + ".class";
        }

        URL url = this.getClass().getResource(lookupResourceName);
        if (url == null) {
            return("Unable to locate resource "+ lookupResourceName);

        }

        String resourceUrl = url.toExternalForm();

        Pattern pattern =
            Pattern.compile("(zip:|jar:file:/)(.*)!/(.*)", Pattern.CASE_INSENSITIVE);

        String jarFilename = null;
        String resourceFilename = null;
        Matcher m = pattern.matcher(resourceUrl);
        if (m.find()) {
            jarFilename = m.group(2);
            resourceFilename = m.group(3);
        } else {
            return "Unable to parse URL: "+ resourceUrl;

        }

        if (!jarFilename.startsWith("C:") ){
          jarFilename = "/"+jarFilename;  // make absolute path on Linux
        }

        File file = new File(jarFilename);
        Long jarSize=null;
        Date jarDate=null;
        Long resourceSize=null;
        Date resourceDate=null;
        if (file.exists() && file.isFile()) {

            jarSize = file.length();
            jarDate = new Date(file.lastModified());

            try {
                JarFile jarFile = new JarFile(file, false);
                ZipEntry entry = jarFile.getEntry(resourceFilename);
                resourceSize = entry.getSize();
                resourceDate = new Date(entry.getTime());
            } catch (Throwable e) {
                return ("Unable to open JAR" + jarFilename + "   "+resourceUrl +"\n"+e.getMessage());

            }

           return "\nresource: "+resourceFilename+"\njar: "+jarFilename + "  \nJarSize: " +jarSize+"  \nJarDate: " +jarDate.toString()+"  \nresourceSize: " +resourceSize+"  \nresourceDate: " +resourceDate.toString()+"\n";


        } else {
            return("Unable to load jar:" + jarFilename+ "  \nUrl: " +resourceUrl);

        }
    } catch (Exception e){
        return e.getMessage();
    }


}

উপরের কোডটি পথে কোনও সংস্থান খুঁজে পাবে। যদি কোনও জারে পাত্রটি খুঁজে পান যে জারের আকার এবং তারিখ এবং জারের মধ্যে সংস্থানটির আকার এবং তারিখটি প্রিন্ট করুন
ডোন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.