ভারার্গস প্যারামিটারের মাধ্যমে সম্ভাব্য গাদা দূষণ


433

আমি বুঝতে পারি জাভা 7 এর সাথে জেনেরিক টাইপের সাথে ভারার্গস ব্যবহার করার সময় এটি ঘটে;

তবে আমার প্রশ্নটি হল ..

"যখন এর ব্যবহার সম্ভবত গাদা কলুষিত করতে পারে" তখন গ্রহটির অর্থ কী?

এবং

নতুন @SafeVarargsটীকাগুলি কীভাবে এটি প্রতিরোধ করে?




আমি এটি আমার সম্পাদকটিতে দেখতে পাচ্ছি:Possible heap pollution from parameterized vararg type
আলেকজান্ডার মিলস

উত্তর:


252

গাদা দূষণ একটি প্রযুক্তিগত শব্দ। এটি এমন রেফারেন্সগুলিকে বোঝায় যেগুলির মধ্যে একটি প্রকার রয়েছে যা তারা দেখায় এমন বস্তুর সুপারটাইপ নয়।

List<A> listOfAs = new ArrayList<>();
List<B> listOfBs = (List<B>)(Object)listOfAs; // points to a list of As

এটি "অবর্ণনীয়" ClassCastExceptionএর দিকে যেতে পারে ।

// if the heap never gets polluted, this should never throw a CCE
B b = listOfBs.get(0); 

@SafeVarargsএটিকে মোটেই বাধা দেয় না। তবে, এমন কিছু পদ্ধতি রয়েছে যা সম্ভবত গাদা দূষিত করবে না, সংকলক কেবল এটি প্রমাণ করতে পারে না। পূর্বে, এই জাতীয় এপিআইয়ের কলকারীরা বিরক্তিকর সতর্কতাগুলি পেতেন যা সম্পূর্ণ অর্থহীন ছিল তবে প্রতিটি কল সাইটে দমন করতে হয়েছিল। এখন এপিআই লেখক এটি ঘোষণার সাইটে একবার দমন করতে পারে।

তবে, পদ্ধতিটি যদি নিরাপদ না হয় তবে ব্যবহারকারীদের আর সতর্ক করা হবে না।


2
সুতরাং আমরা কি বলছি যে গাদাটি দূষিত কারণ এতে উল্লেখ রয়েছে যার প্রকারগুলি আমরা প্রত্যাশা করতে পারি না? (তালিকা <<< বনাম তালিকা <B> আপনার উদাহরণে)
হার্টজস্প্রং


30
এই উত্তরটি হিপ দূষণ কী তা সম্পর্কে একটি সূক্ষ্ম ব্যাখ্যা, তবে এটি কেন সত্যই ব্যাখ্যা করে না যে কেন ভারার্গগুলি নির্দিষ্ট কারণ হিসাবে সতর্কতার জন্য এই কারণে বিশেষত কারণ হতে পারে।
দোলডা 2000 2000

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

237

আপনি যখন ঘোষণা

public static <T> void foo(List<T>... bar) সংকলক এটিকে রূপান্তর করে

public static <T> void foo(List<T>[] bar) তারপরে

public static void foo(List[] bar)

বিপদটি তখন দেখা দেয় যে আপনি ভুল করে তালিকায় ভুল মান নির্ধারণ করবেন এবং সংকলক কোনও ত্রুটি ট্রিগার করবে না। উদাহরণস্বরূপ, যদি Tহয় Stringতবে নিম্নলিখিত কোডটি ত্রুটি ছাড়াই সংকলন করবে তবে রানটাইমে ব্যর্থ হবে:

// First, strip away the array type (arrays allow this kind of upcasting)
Object[] objectArray = bar;

// Next, insert an element with an incorrect type into the array
objectArray[0] = Arrays.asList(new Integer(42));

// Finally, try accessing the original array. A runtime error will occur
// (ClassCastException due to a casting from Integer to String)
T firstElement = bar[0].get(0);

আপনি যদি এই ধরণের দুর্বলতা না রাখেন তা নিশ্চিত করার জন্য যদি আপনি পদ্ধতিটি পর্যালোচনা করে থাকেন তবে আপনি @SafeVarargsসতর্কতা দমন করার জন্য এটিকে বর্নিত করতে পারেন । ইন্টারফেসের জন্য, ব্যবহার করুন @SuppressWarnings("unchecked")

যদি আপনি এই ত্রুটি বার্তাটি পান:

ভারার্গস পদ্ধতিটি অ-পুনঃ-সংশোধনযোগ্য ভারার্গস প্যারামিটার থেকে গাদা দূষণের কারণ হতে পারে

এবং আপনি নিশ্চিত যে আপনার ব্যবহার নিরাপদ তবে তার @SuppressWarnings("varargs")পরিবর্তে আপনার ব্যবহার করা উচিত । দেখুন @SafeVarargs এই পদ্ধতি জন্য একটি উপযুক্ত টীকা করা হয়? এবং https://stackoverflow.com/a/14252221/14731এই দ্বিতীয় ধরণের ত্রুটির একটি সুন্দর ব্যাখ্যার জন্য ।

তথ্যসূত্র:


2
আমি মনে করি আমি আরও ভাল বুঝতে পারছি। বিপদটি তখন আসে যখন আপনি ভ্যারেগগুলি কাস্ট করেন Object[]। যতক্ষণ আপনি কাস্ট করেন না Object[], মনে হয় আপনার ভাল হওয়া উচিত।
djeikyb

3
একটি মূঢ় জিনিস আপনি করতে পারে একটি উদাহরণ হিসাবে: static <T> void bar(T...args) { ((Object[])args)[0] = "a"; }। এবং তারপর কল bar(Arrays.asList(1,2));
djikyb

1
@ ডিজেইকিব যদি বিপদটি কেবল তখনই উত্থাপিত হয় যদি আমি বলি Object[]যে কম্পাইলার যদি আমি না করি তবে সতর্কতা কেন শুরু করবে? সংকলনের সময় এটি পরীক্ষা করা মোটামুটি সহজ হওয়া উচিত, সর্বোপরি (যদি আমি এটিকে একই স্বাক্ষরের সাথে অন্য কোনও ফাংশনে না দিয়ে থাকি, তবে অন্য ফাংশনটি একটি সতর্কবার্তা ট্রিগার করতে পারে)। আমি বিশ্বাস করি না যে এটি সত্যই সতর্কবার্তার মূল ("আপনি কাস্ট না করলে আপনি নিরাপদ"), এবং আমি এখনও বুঝতে পারি না যে আমি কী অবস্থায় আছি।
Qw3ry

5
@ ডিজেইকিব আপনি প্যারামাইট্রাইজড ভেরাগস (উদাঃ bar(Integer...args)) ছাড়াই ঠিক একই বোকা কাজটি করতে পারেন । তাহলে এই সতর্কতার মূল বক্তব্য কী?
ভাসিলি ভ্লাসভ

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

8

@SafeVarargs এটি ঘটতে বাধা দেয় না, তবে এটি আদেশ দেয় যে সংকলকটি ব্যবহার করে এমন কোড সংকলন করার সময় আরও কঠোর।

http://docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs.html এটিকে আরও বিশদে ব্যাখ্যা করে।

ClassCastExceptionজেনারিক ইন্টারফেসে কোনও অপারেশন করার সময় যখন গাদা দূষণ হয় তখন এটি ঘোষণার চেয়ে অন্য ধরণের থাকে।


এর ব্যবহারে অতিরিক্ত সংকলক বিধিনিষেধ বিশেষভাবে প্রাসঙ্গিক বলে মনে হচ্ছে না।
পল বেলোরা

6

আপনি যখন ভারার্গস ব্যবহার করেন, এটির ফলে তৈরি হতে পারে Object[] আর্গুমেন্ট ধরে রাখতে ।

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

এএফআইএকে @SafeVarargsসংকলকের একটি সতর্কতা দমন করে এবং জেআইটি কীভাবে আচরণ করে তা পরিবর্তন করে না।


6
আকর্ষণীয় যদিও এটি সম্পর্কে তার প্রশ্নের সত্যই উত্তর দেয় না @SafeVarargs
পল বেলোরা

1
নাঃ। গাদা দূষণ কী তা নয়। "প্যারামিটারাইজড টাইপের ভেরিয়েবল এমন কোনও বস্তুকে বোঝায় যে সেই প্যারামিটারাইজড টাইপের নয় He সূত্র: docs.oracle.com/javase/tutorial/java/generics/...
Doradus

1

কারণটি হ'ল ভারারাগরা নন-প্যারাম্যাট্রাইজড অবজেক্ট অ্যারে দিয়ে কল করার বিকল্প দেয়। সুতরাং যদি আপনার প্রকারের তালিকা <a> ... ছিল তবে এটিকে তালিকা [] নন-ভারার্গস প্রকারের সাথেও বলা যেতে পারে।

এখানে একটি উদাহরণ:

public static void testCode(){
    List[] b = new List[1];
    test(b);
}

@SafeVarargs
public static void test(List<A>... a){
}

আপনি দেখতে পাচ্ছেন যে তালিকা [] বিতে কোনও ধরণের ভোক্তা থাকতে পারে এবং এখনও এই কোডটি সংকলন করে। যদি আপনি ভারারাগ ব্যবহার করেন তবে আপনি ভাল আছেন তবে আপনি যদি টাইপ-ইরেজরের পরে পদ্ধতি সংজ্ঞাটি ব্যবহার করেন - অকার্যকর পরীক্ষা (তালিকা []) - তবে সংকলক টেম্পলেট প্যারামিটারের প্রকারগুলি পরীক্ষা করবে না। @ সাফেওয়ারগার্স এই সতর্কতাটি দমন করবে।

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