প্রতিবিম্ব সহ জেআইটি অপ্টিমাইজেশন ভাঙ্গা


9

যখন উচ্চ-যুগল একক শ্রেণীর ইউনিট পরীক্ষার সাথে জড়িত হয়েছি তখন আমি নিম্নলিখিত অদ্ভুত আচরণের উপর হোঁচট খেয়েছি (জেডিকে 1.8.0_162 তে পরীক্ষা করা):

private static class SingletonClass {
    static final SingletonClass INSTANCE = new SingletonClass(0);
    final int value;

    static SingletonClass getInstance() {
        return INSTANCE;
    }

    SingletonClass(int value) {
        this.value = value;
    }
}

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

    System.out.println(SingletonClass.getInstance().value); // 0

    // Change the instance to a new one with value 1
    setSingletonInstance(new SingletonClass(1));
    System.out.println(SingletonClass.getInstance().value); // 1

    // Call getInstance() enough times to trigger JIT optimizations
    for(int i=0;i<100_000;++i){
        SingletonClass.getInstance();
    }

    System.out.println(SingletonClass.getInstance().value); // 1

    setSingletonInstance(new SingletonClass(2));
    System.out.println(SingletonClass.INSTANCE.value); // 2
    System.out.println(SingletonClass.getInstance().value); // 1 (2 expected)
}

private static void setSingletonInstance(SingletonClass newInstance) throws NoSuchFieldException, IllegalAccessException {
    // Get the INSTANCE field and make it accessible
    Field field = SingletonClass.class.getDeclaredField("INSTANCE");
    field.setAccessible(true);

    // Remove the final modifier
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    // Set new value
    field.set(null, newInstance);
}

মূল () পদ্ধতির শেষ 2 টি লাইন ইনস্ট্যান্সের মূল্যের সাথে একমত নয় - আমার ধারণা হ'ল ক্ষেত্রটি স্থির চূড়ান্ত হওয়ায় জেআইটি পদ্ধতিটি পুরোপুরি মুক্তি পেয়েছে। চূড়ান্ত কীওয়ার্ড অপসারণ কোড আউটপুটকে সঠিক মান করে।

সিঙ্গেলনের প্রতি আপনার সহানুভূতি (বা এর অভাব) বাদ দেওয়া এবং এক মিনিটের জন্য ভুলে যাওয়া যে এরকম প্রতিচ্ছবি ব্যবহার করা সমস্যার জন্য জিজ্ঞাসা করছে - জেআইটি অপটিমাইজেশনে দোষী হওয়ার জন্য কি আমার এই ধারণাটি সঠিক? যদি তাই হয় - সেগুলি কি কেবল স্থির চূড়ান্ত ক্ষেত্রের মধ্যে সীমাবদ্ধ?


1
একটি সিঙ্গলটন এমন একটি শ্রেণি যার জন্য শুধুমাত্র একটি উদাহরণ উপস্থিত থাকতে পারে। অতএব, আপনার একটি সিঙ্গলটন নেই, আপনার কেবল একটি static finalক্ষেত্র সহ একটি ক্লাস রয়েছে । তদুপরি, এই প্রতিফলন হ্যাকটি জেআইটি বা একমত হওয়ার কারণে ভেঙে গেছে কিনা তা বিবেচ্য নয়।
হোলগার

@ হোলার এই হ্যাকটি কেবলমাত্র একটি শ্রেণীর যে এটি ব্যবহার করে এমন একাধিক পরীক্ষার ক্ষেত্রে সিঙ্গেলটনকে উপহাস করার চেষ্টা হিসাবে ইউনিট পরীক্ষায় করা হয়েছিল। আমি দেখতে পাচ্ছি না যে কীভাবে সামঞ্জস্য হতে পারে (উপরের কোডটিতে কিছু নেই) এবং আমি সত্যিই কী ঘটেছে তা জানতে চাই।
কেল্ম

1
ঠিক আছে, আপনি আপনার প্রশ্নের "অত্যন্ত-একযোগে একক ক্লোন্টেন ক্লাস" বলেছিলেন এবং আমি বলি যে " এটি কোনও বিষয় নয় " যা এটি ভেঙে দেয়। সুতরাং যদি আপনার নির্দিষ্ট উদাহরণ কোডটি JIT এর কারণে ভেঙে যায় এবং আপনি তার জন্য কোনও কাজের আশ্রয় খুঁজে পান এবং তারপরে, সত্যিকারের কোডটি জেআইটির কারণে ব্রেকিং থেকে একত্র হয়ে যাওয়ার কারণে ভেঙে যায়, আপনি কী অর্জন করেছেন?
হোলগার

@ হোলগার ঠিক আছে, শব্দবন্ধটি সেখানে কিছুটা প্রবল ছিল, তার জন্য দুঃখিত। আমি যা বোঝাতে চেয়েছি তা হ'ল - যদি আমরা বুঝতে না পারি যে কেন কিছু মারাত্মকভাবে ভুল হয় আমরা ভবিষ্যতে একই জিনিস দ্বারা দংশিত হওয়ার প্রবণতা বোধ করি, তাই আমি "এটি ঠিক ঘটে" অনুমান করার চেয়ে কারণটি জানতে পারি। যাইহোক, উত্তর দেওয়ার জন্য সময় দেওয়ার জন্য ধন্যবাদ!
কেল্ম

উত্তর:


7

আপনার প্রশ্নকে আক্ষরিক অর্থেই জিজ্ঞাসা করা, " ... আমার ধারণাটি কি সঠিক যে জেআইটি অপ্টিমাইজেশানকে দোষ দেওয়া যায়? ”, উত্তর হ্যাঁ, খুব সম্ভবত এই নির্দিষ্ট উদাহরণে এই আচরণের জন্য জেআইটি অপ্টিমাইজেশানগুলি দায়ী।

তবে static finalক্ষেত্রগুলি পরিবর্তন করার কারণে স্পেসিফিকেশন সম্পূর্ণ বন্ধ রয়েছে, এমন অন্যান্য জিনিস রয়েছে যা এটিকে একইভাবে ভেঙে দিতে পারে। যেমন, জেএমএমের এই জাতীয় পরিবর্তনের স্মৃতি দৃশ্যমানতার জন্য কোনও সংজ্ঞা নেই, সুতরাং, অন্যান্য থ্রেডগুলি যখন এই পরিবর্তনগুলি লক্ষ্য করে তখন তা সম্পূর্ণ অনির্দিষ্ট। এমনকি এটিকে ধারাবাহিকভাবে পর্যবেক্ষণ করার প্রয়োজন নেই, অর্থাত্ তারা নতুন মানটি ব্যবহার করতে পারে, তারপরে আবার পুরানো মানটি ব্যবহার করে, এমনকি সিঙ্ক্রোনাইজেশন আদিমতার উপস্থিতিতেও।

যদিও, জেএমএম এবং অপ্টিমাইজার এখানে যেকোনোভাবে পৃথক করা শক্ত।

আপনার প্রশ্ন “ … সেগুলি কি কেবল স্থির চূড়ান্ত ক্ষেত্রের মধ্যে সীমাবদ্ধ? ”এর উত্তর দেওয়া অনেক কঠিন, কারণ অপ্টিমাইজেশানগুলি অবশ্যই static finalক্ষেত্রের মধ্যে সীমাবদ্ধ নয় , যেমন, অ স্থির finalক্ষেত্রগুলির আচরণ একই নয় এবং তত্ত্ব এবং অনুশীলনের মধ্যেও পার্থক্য রয়েছে।

অ স্থির finalক্ষেত্রগুলির জন্য, প্রতিবিম্বের মাধ্যমে পরিবর্তনগুলি নির্দিষ্ট পরিস্থিতিতে অনুমোদিত। এটি অভ্যন্তরীণ ক্ষেত্রটি পরিবর্তনের ক্ষেত্রে setAccessible(true)হ্যাকিং ছাড়াই এই জাতীয় পরিবর্তন সম্ভব করার পক্ষে যথেষ্ট ।Fieldmodifiers

স্পেসিফিকেশন বলেছেন:

17.5.3। পরবর্তী finalক্ষেত্রগুলির পরিবর্তন

কিছু ক্ষেত্রে যেমন ডিসরিয়ালাইজেশন, সিস্টেমকে finalনির্মাণের পরে কোনও বস্তুর ক্ষেত্র পরিবর্তন করতে হবে । finalপ্রতিবিম্ব এবং অন্যান্য প্রয়োগ-নির্ভর উপায়ে ক্ষেত্রগুলি পরিবর্তন করা যেতে পারে। কেবলমাত্র প্যাটার্নটিতে এটিতে যুক্তিসঙ্গত শব্দার্থবিজ্ঞান রয়েছে এটি হ'ল একটি বস্তু যা নির্মিত হয় এবং তারপরে finalঅবজেক্টের ক্ষেত্রগুলি আপডেট হয় updated অবজেক্টটি অন্যান্য থ্রেডগুলিতে দৃশ্যমান করা উচিত নয় এবং finalক্ষেত্রগুলি পড়া উচিত নয় , যতক্ষণ finalনা অবজেক্টের ক্ষেত্রগুলিতে সমস্ত আপডেট সম্পূর্ণ হয়। finalক্ষেত্রটি স্থির করা হয় এমন নির্মাণকারীর শেষে finalএবং finalপ্রতিবিম্ব বা অন্যান্য বিশেষ পদ্ধতির মাধ্যমে ক্ষেত্রের প্রতিটি পরিবর্তনের সাথে সাথেই জমির হিমশীতল দেখা যায় ।

...

আরেকটি সমস্যা হ'ল স্পেসিফিকেশন finalক্ষেত্রগুলিকে আক্রমণাত্মক অনুকূলকরণের অনুমতি দেয় । কোনও থ্রেডের মধ্যে, কোনও finalক্ষেত্রের কনড্রাক্টর finalসংঘটিত হয় না এমন ক্ষেত্রগুলির পরিবর্তনের সাথে ক্ষেত্রের রিডগুলি পুনরায় অর্ডার করা অনুমোদিত ।

উদাহরণ 17.5.3-1। finalক্ষেত্রগুলির আগ্রাসী অনুকূলকরণ
class A {
    final int x;
    A() { 
        x = 1; 
    } 

    int f() { 
        return d(this,this); 
    } 

    int d(A a1, A a2) { 
        int i = a1.x; 
        g(a1); 
        int j = a2.x; 
        return j - i; 
    }

    static void g(A a) { 
        // uses reflection to change a.x to 2 
    } 
}

ইন dপদ্ধতি, কম্পাইলার সার্চ পুনর্বিন্যাস করতে অনুমতি দেওয়া হয় xএবং কল gঅবাধে। সুতরাং, new A().f()ফিরে আসতে পারে -1, 0অথবা 1

অনুশীলনে, উপরে বর্ণিত আইনী পরিস্থিতিগুলি না ভেঙে আক্রমণাত্মক অনুকূলকরণ সম্ভব এমন সঠিক স্থানগুলি নির্ধারণ করা একটি উন্মুক্ত সমস্যা , সুতরাং -XX:+TrustFinalNonStaticFieldsনির্দিষ্ট না করা পর্যন্ত হটস্পট জেভিএম finalক্ষেত্রের মতো অ স্থির ক্ষেত্রগুলিকে অপ্টিমাইজ করবে না static final

অবশ্যই আপনি যখন ক্ষেত্রটি হিসাবে ঘোষণা করবেন না final, জেআইটি ধরে নিতে পারে না যে এটি কখনই পরিবর্তিত হবে না, যদিও থ্রেড সিঙ্ক্রোনাইজেশন আদিমতার অনুপস্থিতিতে, এটি উপযুক্ত হওয়া কোডের পথে প্রকৃত পরিবর্তনগুলি বিবেচনা করতে পারে (সহ প্রতিফলিত বেশী)। সুতরাং এটি এখনও আক্রমণাত্মকভাবে অ্যাক্সেসটিকে অনুকূল করে তুলতে পারে তবে কেবল যদি পাঠানো এবং লেখাগুলি কার্যকরভাবে থ্রেডের মধ্যে প্রোগ্রাম ক্রমে ঘটে থাকে only সুতরাং আপনি কেবলমাত্র উপযুক্ত সিঙ্ক্রোনাইজেশন কনস্ট্রাকশন ছাড়াই অন্য থ্রেড থেকে এটি দেখার সময় অপ্টিমাইজেশনগুলি লক্ষ্য করবেন।


দেখে মনে হচ্ছে প্রচুর লোকেরা এইগুলি কাজে লাগানোর চেষ্টা করে final, তবে, যদিও কেউ কেউ আরও ভাল পারফরম্যান্ট হিসাবে প্রমাণিত হয়েছে, তবে কিছু সঞ্চয় nsঅন্যান্য কোডের প্রচুর পরিমাণে ভাঙার পক্ষে নয়। কেন শেনানডোহর কয়েকটি পতাকা এটির পিছনে ব্যাক করছে উদাহরণস্বরূপ
ইউজিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.