আমি একটি জটিল ওয়েব অ্যাপ্লিকেশন মোতায়েন করার সময় এবং অজ্ঞাপূর্ণ করার সময় আমি এই সমস্যার বিরুদ্ধে আমার মাথা ঠোঁট করছি এবং ভেবেছিলাম যে আমি একটি ব্যাখ্যা এবং আমার সমাধান যুক্ত করব।
আমি যখন অ্যাপাচি টমক্যাটে একটি অ্যাপ্লিকেশন স্থাপন করি তখন সেই অ্যাপ্লিকেশনের জন্য একটি নতুন ক্লাসলোডার তৈরি হয়। ক্লাসলুডারটি তার পরে অ্যাপ্লিকেশনটির সমস্ত ক্লাস লোড করতে ব্যবহৃত হয়, এবং অজ্ঞাতসারে, সবকিছু সুন্দরভাবে চলে যাওয়ার কথা। তবে বাস্তবে এটি এতটা সহজ নয়।
ওয়েব অ্যাপ্লিকেশনটির জীবনে নির্মিত এক বা একাধিক ক্লাসগুলির স্থির রেফারেন্স রয়েছে যা রেখার পাশাপাশি কোথাও ক্লাসলোডারকে উল্লেখ করে। যেহেতু রেফারেন্সটি মূলত স্থিতিশীল, কোনও পরিমাণ জঞ্জাল সংগ্রহ এই রেফারেন্সটিকে পরিষ্কার করবে না - ClassLoader, এবং এটি যে সমস্ত ক্লাসে বোঝায়, এখানে থাকার জন্য এখানে রয়েছে।
এবং বেশ কয়েকটি রিডপ্লাইয়ের পরে, আমরা আউটঅফমিউরিওরির মুখোমুখি।
এখন এটি মোটামুটি গুরুতর সমস্যা হয়ে দাঁড়িয়েছে। আমি নিশ্চিত করতে পারি যে টমক্যাট প্রতিটি পুনর্নির্মাণের পরে পুনরায় চালু হয়েছে, তবে এটি কেবল অ্যাপ্লিকেশনকে পুনর্বার নিয়োগ না করে পুরো সার্ভারটি নিচে নেবে যা প্রায়শই সম্ভব হয় না।
সুতরাং পরিবর্তে আমি কোডে একসাথে একটি সমাধান রেখেছি, যা অ্যাপাচি টমক্যাট 6.0 এ কাজ করে। আমি অন্য কোনও অ্যাপ্লিকেশন সার্ভারে পরীক্ষা করিনি, এবং অবশ্যই জোর দিতে হবে যে এটি সম্ভবত অন্য কোনও অ্যাপ্লিকেশন সার্ভারে পরিবর্তন ছাড়া কাজ না করে ।
আমি আরও বলতে চাই যে ব্যক্তিগতভাবে আমি এই কোডটিকে ঘৃণা করি এবং বিদ্যমান কোডটি যথাযথ শাটডাউন এবং ক্লিনআপ পদ্ধতি ব্যবহারের জন্য পরিবর্তন করা যায় যদি কেউ এইটিকে "দ্রুত ফিক্স" হিসাবে ব্যবহার না করে । আপনার কোডটির উপর নির্ভর করে যদি কোনও বাহ্যিক গ্রন্থাগার থাকে তবে এটি কেবলমাত্র একবার ব্যবহার করা উচিত (আমার ক্ষেত্রে এটি একটি রেডিয়াস ক্লায়েন্ট ছিল) যা তার নিজস্ব স্ট্যাটিক রেফারেন্সগুলি পরিষ্কার করার কোনও উপায় সরবরাহ করে না।
যাইহোক, কোড সহ। অ্যাপ্লিকেশনটি যেখানে অপ্রকাশিত রয়েছে সেদিকে এটি কল করা উচিত - যেমন সার্লেটের ধ্বংসাত্মক পদ্ধতি বা (আরও ভাল পদ্ধতির) কোনও সার্লেটলেট কনটেক্সটলাইস্টেনারের প্রসঙ্গটি ডিজট্রয়েড পদ্ধতি।
//Get a list of all classes loaded by the current webapp classloader
WebappClassLoader classLoader = (WebappClassLoader) getClass().getClassLoader();
Field classLoaderClassesField = null;
Class clazz = WebappClassLoader.class;
while (classLoaderClassesField == null && clazz != null) {
try {
classLoaderClassesField = clazz.getDeclaredField("classes");
} catch (Exception exception) {
//do nothing
}
clazz = clazz.getSuperclass();
}
classLoaderClassesField.setAccessible(true);
List classes = new ArrayList((Vector)classLoaderClassesField.get(classLoader));
for (Object o : classes) {
Class c = (Class)o;
//Make sure you identify only the packages that are holding references to the classloader.
//Allowing this code to clear all static references will result in all sorts
//of horrible things (like java segfaulting).
if (c.getName().startsWith("com.whatever")) {
//Kill any static references within all these classes.
for (Field f : c.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())
&& !Modifier.isFinal(f.getModifiers())
&& !f.getType().isPrimitive()) {
try {
f.setAccessible(true);
f.set(null, null);
} catch (Exception exception) {
//Log the exception
}
}
}
}
}
classes.clear();