কোনও থ্রেডের প্রসঙ্গ শ্রেনী লোডার এবং একটি সাধারণ বর্গ লোডার মধ্যে পার্থক্য কী?
তা হল, যদি Thread.currentThread().getContextClassLoader()
এবং getClass().getClassLoader()
বিভিন্ন শ্রেণীর লোডার অবজেক্টগুলি ফেরত দেয় তবে কোনটি ব্যবহৃত হবে?
কোনও থ্রেডের প্রসঙ্গ শ্রেনী লোডার এবং একটি সাধারণ বর্গ লোডার মধ্যে পার্থক্য কী?
তা হল, যদি Thread.currentThread().getContextClassLoader()
এবং getClass().getClassLoader()
বিভিন্ন শ্রেণীর লোডার অবজেক্টগুলি ফেরত দেয় তবে কোনটি ব্যবহৃত হবে?
উত্তর:
প্রতিটি ক্লাস অন্যান্য ক্লাস লোড করতে নিজস্ব শ্রেণি লোডার ব্যবহার করবে। সুতরাং যদি ClassA.class
রেফারেন্সগুলি ClassB.class
তখন ClassB
শ্রেণীবদ্ধার ClassA
বা তার পিতামাতার ক্লাসপথে থাকতে হবে ।
থ্রেড প্রসঙ্গে ক্লাসলোডার হ'ল বর্তমান থ্রেডের বর্তমান ক্লাসলোডার। একটি ক্লাস থেকে একটি অবজেক্ট তৈরি করা যেতে পারে ClassLoaderC
এবং তারপরে মালিকানাধীন একটি থ্রেডে প্রেরণ করা যায় ClassLoaderD
। এই ক্ষেত্রে অবজেক্টটি Thread.currentThread().getContextClassLoader()
সরাসরি ব্যবহার করা দরকার যদি এটি নিজস্ব শ্রেণিবোর্ডারে উপলব্ধ না এমন সংস্থানগুলি লোড করতে চায়।
ClassA.class
রেফারেন্স ClassB.class
" বলার অর্থ কী ?
এটি আসল প্রশ্নের উত্তর দেয় না, তবে যেহেতু প্রশ্নটি উচ্চ স্তরের এবং যে কোনও ContextClassLoader
প্রশ্নের জন্য লিঙ্কযুক্ত , আমি প্রাসঙ্গিক শ্রেণীর লোডার কখন ব্যবহার করা উচিত সে সম্পর্কিত প্রশ্নের উত্তর দেওয়া গুরুত্বপূর্ণ বলে আমি মনে করি। সংক্ষিপ্ত উত্তর: প্রসঙ্গ বর্গ লোডার কখনও ব্যবহার করবেন না ! আপনি getClass().getClassLoader()
যখন কোনও ClassLoader
প্যারামিটার অনুপস্থিত এমন কোনও কল করতে হবে তখন সেট করুন ।
যখন একটি শ্রেণীর কোড অন্য ক্লাসটি লোড করতে বলে, সঠিক ক্লাস লোডারটি ব্যবহার করার জন্য কলার ক্লাস (যেমন, getClass().getClassLoader()
) হিসাবে একই শ্রেণীর লোডার । এইভাবে জিনিসগুলি 99.9% সময়ের মতো কাজ করে কারণ আপনি যখন প্রথমবার নতুন ক্লাসের উদাহরণ তৈরি করেন, স্থির পদ্ধতিটি চালু করেন বা কোনও স্থির ক্ষেত্র অ্যাক্সেস করেন তখন JVM নিজেই এটি করে ।
আপনি যখন প্রতিবিম্বটি ব্যবহার করে কোনও ক্লাস তৈরি করতে চান (যেমন কোনও কনফিগারযোগ্য নামযুক্ত শ্রেণীর ডিজিটালাইজেশন বা লোড করার সময়), গ্রন্থাগারটি প্রতিবিম্বটি করে সেগুলি অ্যাপ্লিকেশনClassLoader
থেকে প্যারামিটার হিসাবে সর্বদা কোন শ্রেণীর লোডারটি ব্যবহার করতে হবে সেই আবেদনটি জিজ্ঞাসা করা উচিত । অ্যাপ্লিকেশনটির (যা নির্মাণের প্রয়োজন এমন সমস্ত শ্রেণীর জানে) এটি পাস করা উচিত getClass().getClassLoader()
।
কোনও শ্রেণি লোডার পাওয়ার অন্য কোনও উপায় ভুল is যদি কোনও লাইব্রেরি হ্যাক ব্যবহার করে যেমন Thread.getContextClassLoader()
, sun.misc.VM.latestUserDefinedLoader()
বা sun.reflect.Reflection.getCallerClass()
এটি এপিআই-এর অভাবজনিত একটি বাগ। মূলত, Thread.getContextClassLoader()
কেবলমাত্র বিদ্যমান কারণ ObjectInputStream
এপিআই ডিজাইন করা যিনি ClassLoader
প্যারামিটার হিসাবে গ্রহণ করতে ভুলে গিয়েছিলেন এবং এই ভুলটি আজও জাভা সম্প্রদায়কে ভুতুড়ে ফেলেছে।
এটি বলেছিল যে অনেকগুলি জেডিকে ক্লাস ব্যবহার করতে কিছু বর্গ লোডার অনুমান করতে কয়েকটি হ্যাকগুলির মধ্যে একটি ব্যবহার করে। কেউ কেউ ব্যবহার করেন ContextClassLoader
(যা আপনি যখন ভাগ করা থ্রেড পুলে বিভিন্ন অ্যাপ্লিকেশন চালাবেন বা ব্যর্থ হয়ে যান বা ছেড়ে চলে যান ContextClassLoader null
), কেউ কেউ স্ট্যাকটি হাঁটেন (যা ক্লাসের প্রত্যক্ষ কলার নিজেই লাইব্রেরি হয়ে গেলে ব্যর্থ হয়), কেউ সিস্টেম ক্লাস লোডার ব্যবহার করে (যা ঠিক আছে, যতক্ষণ না এটি কেবলমাত্র ক্লাস ব্যবহারের জন্য ডকুমেন্টেড থাকে CLASSPATH
) বা বুটস্ট্র্যাপ শ্রেণীর লোডার এবং কেউ কেউ উপরের কৌশলগুলির একটি অপ্রত্যাশিত সংমিশ্রণ ব্যবহার করে (যা কেবল জিনিসগুলিকে আরও বিভ্রান্ত করে তোলে)। এর ফলে দাঁত কাঁদতে কাঁদতে এবং কাঁদতে পারে।
এই জাতীয় কোনও এপিআই ব্যবহার করার সময় প্রথমে ক্লাস লোডারকে প্যারামিটার হিসাবে গ্রহণ করে এমন পদ্ধতির একটি ওভারলোড অনুসন্ধান করার চেষ্টা করুন । যদি কোনও বুদ্ধিমান পদ্ধতি না থাকে, তবে ContextClassLoader
এপিআই কলের আগে সেট করার চেষ্টা করুন (এবং এটির পরে পুনরায় সেট করুন):
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
// call some API that uses reflection without taking ClassLoader param
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
জাভাওয়াল্ড.কম এ একটি নিবন্ধ রয়েছে যা পার্থক্যটি ব্যাখ্যা করে => আপনার কোন ক্লাসলডার ব্যবহার করা উচিত
(1)
থ্রেড প্রসঙ্গ শ্রেণীবদ্ধরা শ্রেণিবদ্ধকরণ প্রতিনিধি প্রকল্পের চারপাশে একটি পিছনের দরজা সরবরাহ করে।
উদাহরণস্বরূপ জেএনডিআই নিন: এর সাহসগুলি আরটি.জারে বুটস্ট্র্যাপ ক্লাস দ্বারা প্রয়োগ করা হয়েছে (জেএসইএস ১.৩ দিয়ে শুরু করা), তবে এই মূল জেএনডিআই ক্লাসগুলি স্বাধীন বিক্রেতাদের দ্বারা প্রয়োগ করা জেএনডিআই সরবরাহকারীদের লোড করতে পারে এবং সম্ভাব্যভাবে অ্যাপ্লিকেশনটির-ক্লাসপ্যাটে মোতায়েন করা যেতে পারে। এই দৃশ্যে একটি প্যারেন্ট ক্লাসলোডারকে (এক্ষেত্রে আদিমতম) তার চাইল্ড ক্লাসলোডারগুলির মধ্যে একটিতে দৃশ্যমান কোনও শ্রেণি লোড করার জন্য আহ্বান জানানো হয়েছে (উদাহরণস্বরূপ, সিস্টেমটি)। সাধারণ জে 2 এসই প্রতিনিধি কাজ করে না এবং মূল জেএনডিআই ক্লাসগুলি থ্রেড কনটেক্সট লোডার ব্যবহার করতে পারে, সুতরাং যথাযথ প্রতিনিধি দলের বিপরীতে দিকনির্ধারিতভাবে শ্রেণিবোদ্ধার শ্রেণিবিন্যাসের মাধ্যমে কার্যকরভাবে "টানেলিং" করা হয়।
(২) একই উত্স থেকে:
এই বিভ্রান্তি সম্ভবত জাভার সাথে কিছু সময়ের জন্য থাকবে। যে কোনও প্রকারের গতিশীল রিসোর্স লোডিংয়ের সাথে কোনও জে 2 এসই এপিআই নিন এবং এটি কোন লোডিং কৌশল ব্যবহার করে তা অনুমান করার চেষ্টা করুন। এখানে একটি নমুনা দেওয়া হল:
- জেএনডিআই প্রসঙ্গ শ্রেণীবদ্ধকারী ব্যবহার করে
- Class.getResource () এবং Class.forName () বর্তমান ক্লাসলোডার ব্যবহার করে
- জ্যাকএক্সপি প্রাসঙ্গিক ক্লাসলোডার ব্যবহার করে (J2SE 1.4 হিসাবে)
- java.util.ResourceBundle কলারের বর্তমান শ্রেণি লোডার ব্যবহার করে
- Java.protocol.handler.pkgs সিস্টেমের মাধ্যমে নির্দিষ্ট ইউআরএল প্রোটোকল হ্যান্ডলারগুলি কেবল বুটস্ট্র্যাপ এবং সিস্টেম ক্লাসলোডারগুলিতে সন্ধান করা হবে
- জাভা সিরিয়ালাইজেশন এপিআই ডিফল্টরূপে কলারের বর্তমান ক্লাসলোডার ব্যবহার করে
bootstrap
প্রাসঙ্গিক শ্রেণি লোডার হিসাবে প্রাসঙ্গিক শ্রেণি লোডার হিসাবে সেট করা হচ্ছে না তবে এটির সাথে সেট করা হচ্ছে এমন শিশু system
শ্রেণিপথ শ্রেণি লোডার Thread
। JNDI
ক্লাস তারপর ব্যবহার নিশ্চিত তৈরি করছেন Thread.currentThread().getContextClassLoader()
JNDI বাস্তবায়ন শ্রেণীর ক্লাসপাথ উপলব্ধ লোড করা হয়নি।
@ ডেভিড রাসেল উত্তরে যুক্ত করা, ক্লাসগুলি একাধিক শ্রেণীর লোডার দ্বারা লোড করা যেতে পারে।
শ্রেণি লোডার কীভাবে কাজ করে তা বুঝতে দিন ।
জাভেরিভিজেটে জাভিন পল ব্লগ থেকে:
ClassLoader
তিনটি নীতি অনুসরণ করে।
জাভাতে একটি ক্লাস লোড করা হয়, যখন এটির প্রয়োজন হয়। ধরুন আপনার কাছে অ্যাবসি.ক্লস নামে একটি নির্দিষ্ট শ্রেণীর ক্লাস রয়েছে, এই শ্রেণিটি লোড করার প্রথম অনুরোধ অ্যাপ্লিকেশন ক্লাসলোডারে আসবে যা তার প্যারেন্ট এক্সটেনশন ক্লাসলোডারকে প্রেরণ করবে যা প্রিমর্ডিয়াল বা বুটস্ট্র্যাপ শ্রেণীর লোডারকে আরও প্রতিনিধি প্রেরণ করবে
বুটস্ট্র্যাপ ক্লাসলুডার আরটি.জার থেকে স্ট্যান্ডার্ড জেডিকে ক্লাস ফাইল লোড করার জন্য দায়বদ্ধ এবং এটি জাভার সমস্ত শ্রেণীর লোডারদের পিতা-মাতা। বুটস্ট্র্যাপ শ্রেণীর লোডারটির কোনও বাবা-মা নেই।
এক্সটেনশন ক্লাসলডার তার পিতামাতা, বুটস্ট্র্যাপে শ্রেণি লোডিংয়ের অনুরোধ পেশ করে এবং যদি ব্যর্থ হয় তবে ja.ext.dirs সিস্টেম সম্পত্তি দ্বারা নির্দেশিত অন্য কোনও ডিরেক্টরি ডিরেক্টরি Jre / lib / ext ডিরেক্টরি বা অন্য কোনও ডিরেক্টরি লোড করে class
সিস্টেম বা অ্যাপ্লিকেশন শ্রেণীর লোডার এবং এটি CLASSPATH এনভায়রনমেন্ট ভেরিয়েবল, -ক্লাসপাথ বা -cp কমান্ড লাইন বিকল্প, জেআর-এর ভিতরে ম্যানিফেস্ট ফাইলের ক্লাস-পাথ বৈশিষ্ট্য থেকে অ্যাপ্লিকেশন নির্দিষ্ট ক্লাস লোড করার জন্য দায়ী।
অ্যাপ্লিকেশন শ্রেণির লোডার হ'ল এক্সটেনশন ক্লাসলোডার এবং এটি sun.misc.Launcher$AppClassLoader
শ্রেণীর দ্বারা প্রয়োগ করা হয় ।
দ্রষ্টব্য: বুটস্ট্র্যাপ শ্রেণীর লোডার , যা বেশিরভাগ সিতে স্থানীয় ভাষায় প্রয়োগ করা হয়, বাদে সমস্ত জাভা শ্রেণি লোডার ব্যবহার করে প্রয়োগ করা হয় java.lang.ClassLoader
।
দৃশ্যমানতার নীতি অনুসারে, চাইল্ড ক্লাসলোডার প্যারেন্ট ক্লাসলোডার দ্বারা লোড হওয়া ক্লাস দেখতে পারে তবে তদ্বিপরীতটি সত্য নয়।
এই নীতি অনুসারে প্যারেন্ট দ্বারা লোড করা একটি শ্রেণি আবার চাইল্ড ClassLoader দ্বারা লোড করা উচিত নয়
ClassB
অবশ্যইClassA
'র লোডার'র ক্লাসপথে থাকতে হবে (বাClassA
এর লোডার বাবা-মা)?ClassA
এর লোডারের পক্ষে ওভাররাইড করা কি সম্ভব নয়loadClass()
, যেমন শ্রেণিপথে নাClassB
থাকলেও এটি সফলভাবে লোড করতে পারেClassB
?