සංකීර්ණ වෙබ් යෙදුමක් යෙදවීමේදී සහ යෙදවීමේදී මම මෙම ගැටළුවට එරෙහිව හිස ගසා ඇති අතර, පැහැදිලි කිරීමක් සහ මගේ විසඳුම එකතු කිරීමට සිතුවෙමි.
මම Apache Tomcat හි යෙදුමක් යෙදූ විට, එම යෙදුම සඳහා නව ClassLoader එකක් සාදනු ලැබේ. පංතියේ ලෝඩරය පසුව යෙදුමේ සියලුම පංති පැටවීමට භාවිතා කරන අතර, යෙදවීම මත සෑම දෙයක්ම මනාව ඉවතට යා යුතුය. කෙසේ වෙතත්, යථාර්ථයේ දී එය එතරම් සරල නැත.
වෙබ් යෙදුමේ ජීවිත කාලය තුළ නිර්මාණය කරන ලද පන්ති එකක් හෝ වැඩි ගණනක් ස්ථිතික සඳහනක් ඇති අතර, එය කොතැනක හෝ පන්තියේ ලෝඩරය සඳහන් කරයි. මූලාශ්රය මුලින් ස්ථිතික බැවින්, කසළ එකතු කිරීමේ ප්රමාණයක් මෙම සඳහන පිරිසිදු නොකරයි - පංති ලෝඩරය සහ එය පටවා ඇති සියලුම පන්ති මෙහි රැඳී සිටියි.
නැවත සේවයේ යෙදවීමෙන් පසුව, අපට OutOfMemoryError හමුවෙයි.
දැන් මෙය තරමක් බරපතල ගැටළුවක් බවට පත්ව ඇත. එක් එක් නැවත යෙදවීමෙන් පසුව ටොම්කාට් නැවත ආරම්භ කරන බවට මට සහතික විය හැකිය, නමුත් එමඟින් යෙදුම නැවත සේවයේ යෙදවීමට වඩා සමස්ත සේවාදායකයම ඉවත් කරයි, එය බොහෝ විට කළ නොහැකි ය.
ඒ නිසා මම ඒ වෙනුවට Apache Tomcat 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();