How to unload Java Class كيفية تفريغ جافا الدرجة
I have been asked this question several times. لقد طلب مني في هذه المساله عدة مرات. Recently Xyling asked the same question in his blog. في الآونة الاخيرة وطلب xyling السؤال نفسه في تقريره بلوق. So I thought a simple explanation may be in order. كنت اعتقد حتى مجرد تفسير يمكن ان تكون في النظام.
To unload a class you have to create a custom classloader and load the class using it. لتفريغ فئة لديك لايجاد عرف classloader وتحميل الطبقة استخدامه. Tomcat does it and so does JRun. قط وانه لا.. فهل jrun. You can look in Tomcat code for an example. يمكنك أن تبحث في مدونة قط على سبيل المثال.
After you are done with the class you need to release all references to the class as well as to the class loader by reassigning the variables or setting them to null. بعد انتهائك مع الطبقة انت بحاجة الى اطلاق سراح جميع الاشارات الى الطبقة وكذلك الى اعادة تكليف من قبل الطبقة محمل المتغيرات او تحديد لها لاغيه.
Then either wait for System.gc() to unload the class or you call it directly in a loop till no more bytes can be freed. بعد ذلك اما ان ننتظر system.gc () لتفريغ أو الطبقة أو الدعوة لكم فيه مباشرة في حلقة حتى لا اكثر بايت يمكن ان تتحرر. however normally calling it twice does the trick. ولكن عادة مرتين ووصفه بانه لا حيلة.
Note: You cannot unload a single class. ملاحظه : لا يمكنك تفريغ فئة واحدة. You have to unload the classloader along with it. لديك لتفريغ classloader معه. So obviously System classloader is not the suitable for this task. ومن الواضح ان ذلك النظام classloader ليست مناسبة لهذه المهمة.
Note 2: This is how JSP pages are reloaded dynamically everytime you change the code. ملاحظه 2 : التخطيط الاستراتيجي المشترك وهذه هي الطريقة التي يتم اعادة تحميل صفحات ديناميكيه في كل مرة تقوم بتغيير هذا القانون. And yes that is why first time takes much longer to load then subsequent times. نعم وهذا هو السبب في المرة الاولى يأخذ وقتا اطول لتحميل اوقات لاحقة بعد ذلك.
Filed under المقدم بمقتضى How To كيف , ، Java Software برنامج جافا , ، Technology التقنيه | |
| |
RSS 2.0 ار اس اس 2،0 | |
Email this Article ارسل هذه المادة
You may also like to read ويمكنك ايضا ان تقرأ |




March 15th, 2005 at 6:31 pm مارس 15th ، 2005 في الساعة 6:31
Hi, اهلا ،
Thank you very much for this information. اشكركم جزيل الشكر على هذه المعلومات.
Mind if I extend my question here itself? اذا كان الاعتبار الأول والسؤال المطروح هنا اتقدم نفسها؟ Actually, I load my classes through URLClassLoader. والواقع انني تحميل الطبقات من خلال urlclassloader بلدي. And generally I am loading JAR files through URLClassLoader. وعموما انا تحميل ملفات من خلال جرة urlclassloader. Now I want this JAR file to be unloaded. الآن اريد هذا الملف الجره ستفرغ. Can I extend your logic to URLClassLoader for JAR files too? هل يمكنني قم منطق urlclassloader لجره الى الملفات ايضا؟
March 15th, 2005 at 6:33 pm مارس 15th ، 2005 في الساعة 6:33
Thank you. شكرا لك.
March 15th, 2005 at 6:41 pm مارس 15th ، 2005 في الساعة 6:41
Actually, the JSP first-load time is not ONLY due to the class being reloaded, (loading a class from the bytecode doesn’t take that long, if it did Java would be a lot slower than it is ;-). وفي الواقع ، فإن التخطيط الاستراتيجى المشترك للتحميل مرة الاولى ليس فقط بسبب اعادة تحميل الطبقة يجري ، (تحميل فئة من bytecode لا يأخذ أن طويل ، لو لم جافا سيكون ابطأ كثيرا مما هو عليه ؛-). A more significant amount of time is spent generating the bytecode, as a change to the JSP source has to be converted first into Java source, and then in to byte-code, which can then be loaded by the ClassLoader. أكثر قدر كبير من الوقت ينفق على توليد bytecode ، وإجراء تغيير فى التخطيط الاستراتيجى المشترك المصدر الاول لتحويلها الى مصدر جافا ، وبعد ذلك في لبايت - قانون ، وعندئذ يمكن تحميلها من قبل classloader. So, add two parse/generate cycles to one byte load… بذلك ، اضافة اثنين من اعراب / دورات لتوليد تحميل بايت واحد…
March 16th, 2005 at 4:28 pm مارس 16th ، 2005 في الساعة 4:28
If you are interested in seeing an interesting twist on dynamic reloading of classes, check out the source in our plugin engine at اذا كنت ترغب في رؤية مثيرة للاهتمام تويست على ديناميه اعادة شحن الطبقات ، راجع المصدر في البرنامج المساعد في المحرك http://www.platonos.org . We not only load plugins, each with their own classloader, but we are now adding the ability to dynamically unload portions of a plugin that are dependent on another. ونحن ليس فقط تحميل ملحقات ، لكل منها classloader ، ولكن نحن الآن في اضافة القدرة على ديناميكيه تفريغ اجزاء من البرنامج المساعد التي تعتمد على آخر.
As it turns out, when plugin A provides an interface that plugin B provides an implementation for, the plugin B ClassLoader (through delegation to A’s classloader) holds a lock on the implementation Class itself. وكما تبين ، عند وضع البرنامج المساعد ويوفر واجهة البرنامج المساعد (ب) ان يقدم للتنفيذ ، فان البرنامج المساعد classloader ب) من خلال الوفد الى 'sclassloader) يحمل لوك على تنفيذ الطبقة نفسها. Even after we null out the classloader in plugin A (if we are trying to unload A), B’s classloader keeps a lock on A because of the interface Class that B’s implementation class keeps a lock on. ونحن لاغيا حتى بعد بيان classloader في البرنامج المساعد (أ) (وإذا نحن نحاول تفريغ أ) و (ب 'sclassloader تحتفظ لوك على التفاعل بسبب طبقة ب تنفيذ الطبقة تحتفظ قفل. Basically you have this: هذا اساسا لديك :
interface pluginAInterface{} واجهة pluginainterface ()
class pluginBImpl implements pluginAInterface{} الطبقة pluginbimpl تنفذ pluginainterface ()
each is loaded by a different classloader. كل من تحميلها من قبل مختلف classloader. When used, plugin B’s classloader sees that pluginBImpl implements pluginAInterface. وعندما تستخدم البرنامج المساعد للclassloader ب pluginbimpl يرى ان ينفذ pluginainterface. It starts in plugin B’s classloader looking for it. ويبدأ البرنامج المساعد في باء classloader أتطلع لذلك. It can’t find it there (because the pluginAInterface Class is in plugin A’s classloader classpath). ولا يمكن ان تجد هناك (لأن الطبقة pluginainterface في البرنامج المساعد الف classloader classpath). The plugin engine delegates the lookup to plugin A’s classloader to find the byte code for this pluginAInterface Class. فان محرك البرنامج المساعد للمندوبين لبحث البرنامج المساعد الف classloader تياب لايجاد قانون لهذه الدرجة pluginainterface. It’s found there, so plugin A’s classloader “loads” the bytecode, but plugin B’s classloader “sees” the bytecode by initially delegating to A to find it. انها وجدت هناك ، حتى البرنامج المساعد الف classloader "الاحمال" bytecode ، ولكن البرنامج المساعد للclassloader ب "يرى" في البداية من جانب bytecode الى تفويض للبحث عنه. Once found, a classloader’s built in cache stores the classloader:class pointer (meaning, the classloader AND the class make up a sort of “key” as a pointer to the actual bytecode in memory) so it no longer needs to delegate to A. BUT, the big problem is that the pluginBImpl Class maintains it’s own list of interfaces it implements, primarily their Class reference. وجدت مرة واحدة ، classloader بنيت في ذاكرة التخزين المؤقت للمتاجر classloader : الطبقة مؤشر (معنى ، والطبقة classloader تشكل نوعا من "مفتاح" باعتبارها المؤشر الفعلي لbytecode في الذاكرة) حتى انها لم تعد بحاجة الى مندوب ألف ولكن المشكلة الكبيرة هي ان الطبقة pluginbimpl انه يحافظ على القائمة الخاصة به الوصلات التي تنفذ بها ، وبصفة اساسية من الدرجة الاشارة. The bad thing about this is there is no way to set this to null at runtime! والسيءه وهذا هو ما اسفرت عنه لا توجد وسيلة لوضع هذا لاغيا في وقت التشغيل!
So our trick is to use a second classloader within a plugin to allow each interface implemented by another plugin to have it’s own classloader so we can discard that one to get reloading/unloading to work. حتى حيلة لنا هو استخدام classloader الثانية ضمن البرنامج المساعد لاتاحة الفرصة امام كل واجهة من جانب اخر تنفيذ البرنامج المساعد الى انه قد classloader الخاصة بها بحيث يمكننا تجاهل ان واحد للحصول على اعادة التحميل / التفريغ للعمل.
It’sa bit tricky, but it does the trick. It'sa قليلا الى المهاره ، ولكنها الحيله. Probably still more hidden issues we haven’t come across yet. وربما لا تزال اكثر المسائل الخفيه نحن لم نأت عبر حتى الآن.
March 18th, 2005 at 3:00 am مارس 18th ، 2005 في 3:00 صباحا
@Goldy Lukka Yes. @ Goldy lukka نعم. You should be able to. هل ينبغي أن تكون قادرة على. However I haven’t used URLClassLoader in this fashion, so I am not sure if it has any hard-to-remove references. بيد انني لم تستخدم urlclassloader على هذا النحو ، حتى انني لست متأكدا اذا كانت تترتب عليه اية بجد الى حذف الاشارات. I guess a spike solution is in order اعتقد ان الحل هو وضع المسمار في النظام
BTW: I enjoy your site. راجع للشغل : انا استمتع موقعك.
@Kevin Thanks for the very informative comment. @ كيفن شكره للتعليق جدا بالمعلومات.
March 19th, 2005 at 2:54 am مارس 19th ، 2005 في الساعة 2:54
Goldy Lukka, Goldy lukka ،
The trick to using URLClassLoader to reload or unload .jar files is making sure that NO other code is referencing any of the classes within the .jar file. استخدام الحيله لurlclassloader اعادة تحميل أو تفريغ. جرة الملفات هو التأكد من ان القانون لا يشير الى اي من الفئات ضمن. الجره الملف. Dependencies are difficult to manage. التبعيات يصعب السيطرة عليها. We have gone to great pains to try to resolve unload/reload with the issue of plugins depending on one another. لقد ذهبت الى متاعب كبيرة لمحاولة التوصل الى حل لتفريغ / اعادة التحميل مع قضية ملحقات اعتمادا على بعضها البعض. We still have problems in many cases making it happen. ما زالت لدينا مشاكل في كثير من الحالات من القول الى الفعل. In some cases, developers of plugins just have to be aware that if they want to make their plugin as dynamic as possible, they really have to develop it in such a way that they properly clean up any references they have on other plugin classes. وفي بعض الحالات ، ملحقات للمطورين فقط الى ان ندرك انه اذا كانت تريد ان تجعل البرنامج المساعد ديناميه قدر الامكان ، انها حقا لتطويره في مثل هذه الطريقة انها على الوجه الصحيح في تنظيف اي اشارة لها البرنامج المساعد على الطبقات الاخرى.
If your .jar file is just adding implementations to say, a core applications interface API, you should be able to easily remove it. اذا كان جهازك. الجره الملف هو مجرد اضافة الى التطبيقات اقول ، API واجهة التطبيقات الاساسية ، يجب ان تكون قادرة على ازالته بسهولة. As we discovered, an implemting class keeps a reference (lock) on the interface it implements. كما اكتشفنا ، وتبقى الطبقة implemting اشارة (لوك) عن التفاعل وهي تنفذ. So the class in your .jar file would keep the ref to the interface, which is ok, you simply null it out and/or null the classloader that loaded the .jar and you are fine. حتى تلك الفئة الخاصة بك. الجره الملف من شأنه ان يبقى المرجع الى واجهة ، وهو طيب ، انت مجرد انه من اصل لاغيه و / او لاغيه فان classloader التي حملت. جرة وانت بخير. If however the .jar file provides interfaces that other classes (maybe from other .jar files) make use of, that becomes more difficult. ولكن اذا كان. الجره الملف الوصلات التي تنص على فئات أخرى (وربما من غيرها. جرة الملفات) استخدام ، على ان تصبح اكثر صعوبة. Any class outside of the classloader that loaded the .jar file making use of any class from inside the loaded .jar has to also be unloaded. أي فئة من خارج classloader التي حملت. الجره الملف الاستفادة من اي فئة من داخل تحميله. الجره قد يكون ايضا لتفريغ. Again, referring to our engine, it starts a chain reaction of unloading events that can be difficult to manage. مرة اخرى ، مشيرا الى محرك لدينا ، وهي تبدأ سلسلة من ردود الفعل من تفريغ الاحداث التي يمكن ان يكون من الصعب ادارتها. We solved the problem by having two classloader instances per plugin. ونحن الى حل للمشكلة وجود اثنين من classloader البرنامج المساعد لكل الحالات. One that handles the interfaces that are implemented by other plugin classes, and one for the rest of the classes. واحد والتي تعالج الوصلات التي يجري تنفيذها من قبل الطبقات الاخرى البرنامج المساعد ، واحد بالنسبة لبقية الصفوف. It’s not pretty, but thus far it works. انها ليست جميلة ، ولكنها تعمل حتى الآن. We are still experimenting to make this a better process. ونحن لا زلنا تجريب لجعل هذه العملية على نحو افضل.
March 22nd, 2005 at 7:35 pm اذار / مارس 22nd ، 2005 في الساعة 7:35
Kevin, كيفن ،
It’s true that you can’t null the reference to the interface class ( Class#getInterfaces() ), if this was possible it would mean that you remove the interface in the byte code at runtime, from: صحيح انه لا يمكنك اغيه الاشارة الى واجهة من الدرجة (الدرجة getinterfaces # ()) ، إذا كان هذا ممكنا من شأنه ان يعني عليك ان تزيل التداخل في قانون بايت في وقت التشغيل ، من :
public class MyTestImpl implements TestImpl الطبقة العامة mytestimpl تنفذ testimpl
{ (
} )
to الى
public class MyTestImpl الطبقة العامة mytestimpl
{ (
} )
The same is true for superclasses. وينطبق الشيء نفسه على superclasses.
March 23rd, 2005 at 6:23 pm مارس 23rd ، 2005 في الساعة 6:23
it’s great information that how plugins are works. انها كبيرة من المعلومات التي هي ملحقات كيف يعمل. Can i have the simplest possible code of custom class loader. ويمكن لي بابسط ما يمكن من قانون العرف محمل الدرجة. Ultimately the custom class loader is nees to be loaded by the default classloader or not? في نهاية المطاف هو العرف الدرجة محمل nees يجب تحميل classloader تقصير من قبل أم لا؟ If so then will i be able to see to classloader in the callgraph of such kind of program? وإذا كان الأمر كذلك ، ثم انني سوف نكون قادرين على ان نرى لclassloader في callgraph من هذا النوع من البرنامج؟
April 1st, 2005 at 6:02 am نيسان / ابريل 1st ، 2005 في الساعة 6:02
@Sandip Why not use the URLClassLoader? @ Sandip لماذا لا تستخدم urlclassloader؟ Also there is a sample ClassLoader code provided in Java Tutorials. وهناك ايضا عينه classloader وينص القانون على دروس خصوصيه في يافا.
September 11th, 2006 at 11:39 am الحادي عشر ايلول / سبتمبر ، 2006 في الساعة 11:39
Thanks for the information. شكرا لهذه المعلومات.
I read something on the internet which I think is important for some people here: وأنا أقرأ شيئا على شبكة الانترنت الذي اعتقد انه امر هام بالنسبة لبعض الناس هنا :
Two classes are not of the same package if they are loaded by different ClassLoader objects! فصلين لم تكن من نفس المجموعة اذا ما حملت من قبل مختلف الاجسام classloader!
Let’s say you have a package with two classes, one is public and the other package-private. لنقل ان لديك مجموعة مع فصلين ، هو واحد من القطاعين العام والخاص - مجموعة اخرى. These should be loaded by the same ClassLoader(or subclass) object. وينبغي ان تكون هذه تحميلها من قبل نفس classloader (او الفرعية) وجوه. If you don’t you get a runtime error when the public class tries to access the package-private class. اذا كنت لا تحصل على اي خطأ في وقت التشغيل عند العامة من الدرجة يحاول الوصول الى مجموعة من الدرجة العام والخاص.
So if you planned to make a new ClassLoader object for every class, consider using one ClassLoader object for each package. حتى اذا كنت تخطط لتقديم وجوه جديدة لclassloader كل طبقة ، النظر في استخدام classloader هدف واحد عن كل مجموعة. The other option is to make all classes public. الخيار الآخر هو جعل جميع فئات الجمهور.