December 25, 2011

ကလပ်စ်လုဒ်ဒါ (ClassLoader)

အီးဇီးဆာဗလက် ခေါင်းစဉ်ဖြင့် ဆာဗလက် အခြေခံ အကြောင်းများကို ဖော်ပြလာခဲ့သည်မှာ ယခုဆိုလျှင် ၉ကြိမ်မြောက်ကို ရောက်ရှိခဲ့ပြီ ဖြစ်၏။ ရေးမည်ဆိုလျှင် အများကြီး ကျန်ရှိပါသေးသည်။ သို့ပါသော်လည်း အခြားသော အကြောင်းအရာများကိုလည်း ဆက်ချင်ပါသေးသောကြောင့် အီးဇီးဆားဗလက်ကို ဤနေရာတွင် တခန်းရပ်ပါမည်။ နောက်ဆုံးဆိုတော့ ရွေးရခက်ပါသည်။ Security အကြောင်းကို ပဲဆက်ရေးရင်ကောင်းမလား၊ Database နဲ့ပတ်သက်တဲ့ အကြောင်းကိုရေးရင် ကောင်းမလား အမျိုးမျိုးစဉ်းစား ခဲ့ပါသည်။

Security နှင့်ပတ်သက်ပြီး၊ အခြားသော Java EE အကြောင်းဖော်ပြရင်း၊ နောက်ပြီး Security ခေါင်းစဉ်အနေဖြင့်လည်း ဖော်ပြချင်ပါသဖြင့်၊ အခြေခံ အီးဇီး ဆာဗလက်တွင် တကူးတက ဖော်ပြရန်မလိုပေ။ Database ကလည်း အရင်ဆုံး ဆာဗလက်ဘက်မှ မဟုတ်ပဲ အရင်ဆုံး အခြေခံ SQL၊ Database မှစ၍ JDBC၊ JDO နှင့် JPA အစရှိသည့်Java နှင့် ပတ်သက်သော Database အကြောင်းအရာများကို နောက်နှစ်ထဲတွင် ဖော်ပြရန်လည်း စီစဉ်ထားပါသည်။

ဆာဗလက်အတွက် ဘာများကျန်သေးသလဲဟု စဉ်းစားရာတွင်၊ လွန်စွာမှအရေးပါသော Multithread အကြောင်းကို သွားသတိရပါသည်။ ဆာဗလက်သည် Multithread ကို အခြေခံ၍အသုံးပြုထား၏။ သတိမမှုပဲ ရေးမိပါက မမျှော်လင့်သော ဒုက္ခများ ကျရောက်တတ်ပေသည်။ ထို့အတွက် ဤနေရာတွင် ClassLoader အကြောင်းကို ဖော်ပြပြီး ဆာဗလက်ကိုရေးသားလျှင် သတိထားသင့်သည့် အကြောင်း အရာများကို ဖော်ပြသွားပါမည်။

ကလပ်စ်လုဒ်ဒါ (ClassLoader)

ကလပ်စ်လုဒ်ဒါသည် ကလပ်စ်တစ်ခုအား မံမိုရီအပေါ် ခေါ်ယူသည့်အခါတွင်၎င်း၊ ထိုကလပ်စ်မှ အသုံးပြုမည့် အချက်အလက် (resource) များကို ရှာဖွေသည့် အခါတွင်၎င်း အသုံးပြုသော အော့ဘဂျက် တစ်ခုဖြစ်ပြီး၊ java.lang.ClassLoader အား အမွေဆက်ခံ၍ ရေးသားထားသော ကလပ်စ်၏ အင်စတန့်စ် တစ်ခုဖြစ်၏။ Java ကလပ်စ်များအားလုံးသည် အပလီကေးရှင်း စတင်ချိန်တွင်၊ ကလပ်စ်လုဒ်ဒါများ၏ ခေါ်ယူမှု့ကြောင့် မံမိုရီအပေါ်ကို ရောက်ရှိလာပြီး၊ ထိုကလပ်စ်များမှလည်း မိမိအားခေါ်ယူသည့် ကလပ်စ် လုဒ်ဒါများကို သိရှိနိုင်ပါသည်။ အဘယ်ကြောင့်ဆိုသော် Java တွင် အသုံးပြုသော ကလပ်စ်များ အားလုံးသည် java.lang.Class အား အမွေဆက်ခံထားကြပြီး၊ java.lang.Class ၏ getClassLoader မက်သတ်ကို အသုံးပြုခြင်းအားဖြင့် မိမိအား ခေါ်ယူခဲ့သော ကလပ်စ်လုဒ်ဒါကို သိရှိနိုင်ခြင်းဖြစ်၏။

ကလပ်စ်လုဒ်ဒါသည် သစ်ပင် (Tree) ဖွဲ့စည်းပုံကို အသုံးပြုထားပြီး၊ ပတ်သက်ရာ မိဘ လုဒ်ဒါတစ်ခုမှ အမွေဆက်ခံ ထားနိုင်ပါသည်။ ကလပ်စ်လုဒ်ဒါအားလုံး၏ ပင်မကလပ်စ်လုဒ်ဒါအား Bootstrap Class Loader ဟုခေါ်ဆိုပြီး၊ Java ဒြပ်မဲ့စက် (JVM) တွင် တိုက်ရိုက်ရေးသားထားပြီး၊ အပလီကေးရှင်းတစ်ခုအား စတင် အလုပ်လုပ်စေသည့်အခါတွင် ဦးစွာခေါ်ယူမည့် ကလပ်စ် လုဒ်ဒါဖြစ်၏။ Bootstrap ကလပ်စ် လုဒ်ဒါသည် Java ၏ အခြေခံ လိုင်ဘရီကလပ်စ်များ၊ jre/lib/ext ၏ အောက်တွင် ဖြည့်စွက်ထားသော ပြင်ပလိုင်ဘရီ များမှ ကလပ်စ်များကို ခေါ်ယူရာတွင် အသုံးပြုနိုင်ပါသည်။

Bootstrap ကလပ်စ်လုဒ်ဒါ၏ အောက်တွင် တည်ရှိသည်မှာ၊ စစ္စတမ် ကလပ်စ်လုဒ်ဒါဖြစ်ပြီး Bootstrap ကလပ်စ် လုဒ်ဒါ၏ တစ်ခုတည်းသော သားသမီးကလပ်စ်လုဒ်ဒါ (Sub ClassLoader) ဖြစ်၏။ စစ္စတမ်ကလပ်စ် လုဒ်ဒါသည် CLASSPATH အတွင်းရှိ ကလပ်စ်များအား ခေါ်ယူရာတွင်၎င်း၊ ရီဆို့ (Resource) ဖိုင်များအား ရှာဖွေရာတွင်၎င်း အသုံးပြုသော ကလပ်စ် လုဒ်ဒါဖြစ်ပြီး၊ Java အပလီကေးရှင်း တစ်ခုတွင် လွန်စွာမှ အရေးပါအရာရောက်သော နေရာတွင် တည်ရှိပါသည်။ တဖန် ကိုယ်တိုင်ရေးသားထားသော ကလပ်စ်လုဒ်ဒါ တစ်ခုသည် အထွေအထူး သတ်မှတ်ရေးသားထားခြင်း မရှိပါက စစ္စတမ်ကလပ်စ်လုဒ်ဒါ၏ သားသမီး အဖြစ်သတ်မှတ်ခံရမည် ဖြစ်ပြီး၊ လွန်စွာမှအခြေခံကျသော ကလပ်စ်လုဒ်ဒါဟုလည်း ပြောနိုင်ပေသည်။


ကလပ်စ်လုဒ်ဒါများတွင် အထက်အောက် ပတ်သက်မှု့သည် လွန်စွာမှအရေးကြီး၏။ ပုံမှန်အားဖြင့် ကလပ်စ်လုဒ်ဒါတစ်ခုသည် ကလပ်စ်တစ်ခုအား လုဒ်လုပ်ရာတွင် ဦးစွာ မိမိ၏ အထက်မှ၊ ကလပ်စ်လုဒ်ဒါအား တာဝန်ပေး၍ အခေါ်ခိုင်းမည်ဖြစ်၏။ မိမိ၏ မိဘအားအားကိုး၍ မရမှသာ ကိုယ်တိုင်ခေါ်ယူမည် ဖြစ်သည်။ ကလပ်စ်အားလုံးသည် စစ္စတမ်ကလပ်စ်လုဒ်ဒါအား အမွေဆက်ခံ၍ ရေးသားထားသည် ဖြစ်ပါသောကြောင့်၊ CLASSPATH တွင်ရှိသော ကလပ်စ်များအားလုံးအား စစ္စတန်ကလပ်စ်လုဒ်ဒါမှ ခေါ်ယူနိုင်ခြင်း ဖြစ်၏။

တဖန် အပလီကေးရှင်းများသည် မိန်းသရဒ်  (Main Thread) အပါအဝင် မည်သည့် သရဒ်  (Thread) အပါအဝင် Context Class Loader တစ်ခုကို ပိုင်ဆိုင်ကြ၏။ Context ကလပ်စ်လုဒ်ဒါ ဆိုသည်မှာ ထိုသရက် အတွင်းရှိ ကလပ်စ်များကို လုဒ်လုပ်ရန် တာဝန်ရှိပါသည်။ ဤထူးခြားချက်ကို အသုံးပြုခြင်း အားဖြင့် သရက်တစ်ခု အတွင်းမှ မိမိ၏ မိဘတွင် လုဒ်မလုပ်နိုင်သော ကလပ်စ်များအား လုဒ်လုပ်နိုင်ရန် ဒီဇိုင်းရေးဆွဲနိုင်ပါသည်။ Context Class Loader များသည် မိမိ၏ မိဘနေရာတွင်ရှိသော သရဒ်များတွင် သတ်မှတ်ရေးသားရန် လိုအပ်ပါသည်။ အကယ်၍ သရဒ် တစ်ခုအား စတင်ခေါ်ယူရာတွင် Context Class Loader ကို ရေးသားထားခြင်းမရှိပါက လက်ရှိ သရဒ်၏ Context ကလပ်စ် လုဒ်ဒါအား အသုံးပြုသွားမည် ဖြစ်သည်။ Context ကလပ်စ်လုဒ်ဒါအား သတ်မှတ်ရာတွင် java.lang.Thread ၏ setContextClassLoader အား အသုံးပြုနိုင်ပြီး၊ ကလပ်စ်လုဒ်ဒါအား ခေါ်ယူရာတွင် getContextClassLoader မက်သတ်ကို အသုံးပြုနိုင်ပါသည်။


Tomcat ၏ ကလပ်စ်လုဒ်ဒါ

Tomcat သည် သရဒ် (Thread) ပေါင်းများစွာဖြင့် ဖွဲ့စည်းထားသော ရှုပ်ထွေးသော Java အပလီကေးရှင်း တစ်ခုဖြစ်၏။ အဓိကအားဖြင့် အောက်ပါအတိုင်း ကလပ်စ်လုဒ်ဒါများအား ဖွဲ့စည်းထား၏။



Tomcat တွင်၊ ပါဝင်သော ဝဘ်အပလီကေးရှင်းတိုင်းတွင် ကလပ်စ်လုဒ်ဒါများကို သတ်မှတ်ထားကြပါသည်။  ကလပ်စ်လုဒ်ဒါများက ရှာဖွေရန်နေရာများသည် WEB-INF/classes ၏ အောက်ရှိ ကလပ်စ်ဖိုင်များနှင့် WEB-INF/lib ၏အောက်ရှိ jar ဖိုင်များဖြစ်ကြ၏။ ဆာဗလက်အား အလုပ်လုပ်စေသော သရဒ်၏ Context ကလပ်စ် လုဒ်ဒါသည်လည်း အထက်ပါ ကလပ်စ် လုဒ်ဒါပင်ဖြစ်၏။

ဝဘ်အပလီကေးရှင်း အသီးသီး၏၊ မိဘနေရာတွင်ရှိသော လုဒ်ဒါသည် Shared ကလပ်စ် လုဒ်ဒါဖြစ်၏။ shared/classes ၏ အောက်ရှိ ကလပ်စ်ဖိုင်များနှင့် shared/lib ၏ အောက်ရှိ jar ဖိုင်များရှိ ကလပ်စ်များကို ခေါ်ယူအသုံးပြုနိုင်၏။ Shared ကလပ်စ် လုဒ်ဒါအား ဝဘ် အပလီကေရှင်း အားလုံးမှ ဘုံအသုံးပြုနိုင်ပါသဖြင့် shared/classes နှင့် shared/lib အောက်ရှိ ကလပ်စ်နှင့် ရင်းမြစ်များအား ဝဘ်အပလီကေးရှင်းများ အားလုံးမှ အသုံးပြုနိုင်ခြင်း ဖြစ်၏။

Catalina ကလပ်စ် လုဒ်ဒါသည် Tomcat ဆာဗာအား ခေါ်ယူရာတွင် အသုံးပြုသော လုဒ်ဒါဖြစ်၏။ ထို ကလပ်စ် လုဒ်ဒါအား အခြားသော ဝဘ် အပလီကေးရှင်းများမှ ခေါ်ယူအသုံးပြုနိုင်စွမ်း မရှိပေ။ ဤနည်းအားဖြင့် Context ကလပ်စ် လုဒ်ဒါတစ်ခုမှ ခေါ်ယူထားသော ကလပ်စ်များ၊ ရင်းမြစ်များအား အခြားသော အပလီကေးရှင်းများမှ အသုံးပြုခြင်းမရှိစေနိုင်ရန် စီမံထားနိုင်ပါသည်။

Common ကလပ်စ် လုဒ်ဒါသည်၊ Catalina နှင့် Shared ကလပ်စ် လုဒ်ဒါများ၏ မိဘနေရာတွင်ရှိသော ကလပ်စ် လုဒ်ဒါများ ဖြစ်ကြ၏။ တနည်းအားဖြင့် Tomcat နှင့် အားလုံးသော ဝဘ်အပလီကေးရှင်း များတွင် ဘုံအနေဖြင့် အသုံးပြုနိုင်မည် ဖြစ်၏။ Tomcat ၏ common/lib၊ common/classes နှင့် common/endorsed ၏ အောက်ရှိ ရင်းမြစ်များနှင့် ကလပ်စ်များကို ရှာဖွေ အသုံးပြုနိုင်ပါမည်။

နောက်ဆုံးတွင် Tomcat ၏ Class Loader များမှ ခေါ်ယူအသုံးပြုမည့် အစီအစဉ်ကို ဖော်ပြသွားပါမည်။ ပုံမှန် အပလီကေးရှင်းများတွင် ကလပ်စ် လုဒ်ဒါများသည် မိမိ၏ မိဘများ၏ ကလပ်စ်လုဒ်ဒါများကို ဦးစွာအသုံးပြုမည်ဖြစ်သော်လည်း၊ Tomcat ၏ ခေါ်ယူပုံမှာ တမူထူးခြားပါသည်။

Tomcat ၏ ဝဘ်အပလီကေးရှင်းများတွင် ကလပ်စ်များကို ရှာဖွေရာတွင် အောက်ပါ အစီအစဉ် အတိုင်း ခေါ်ယူသွားမည် ဖြစ်၏။
  1. မိမိ၏ ကိုယ်ပိုင် ကလပ်စ် လုဒ်ဒါ
  2. Common  ကလပ်စ် လုဒ်ဒါ
  3. Shared  ကလပ်စ် လုဒ်ဒါ
  4. စစ္စတမ်  ကလပ်စ် လုဒ်ဒါ
  5. Bootstrap  ကလပ်စ် လုဒ်ဒါ


Web Application များတွင် ကလပ်စ်များအား ဘုံအနေဖြင့် အသုံးပြုရာတွင် သတိထားရန် အချက်များ

Tomcat ဆာဗာကို အသုံးပြုသည့်အခါတွင် shared နှင့် common ၏ အောက်ရှိ ကလပ်စ်ဖိုင်များ၊ jar ဖိုင်များနှင့် ရင်းမြစ်ဖိုင်များသည် မည်သည့် ဝဘ်အပလီကေးရှင်းက မဆို အသုံးပြုနိုင်ပါသည်။ သို့ရာတွင် ဤကဲ့သို့ ကလပ်စ်တစ်ခုအား ဘုံအဖြစ် အသုံးပြုရာတွင် သတိပြုစရာ အချက်တစ်ခုရှိ၏။ ကလပ်စ် ကိန်းရှင် (Class Variables) များပင် ဖြစ်၏။

အင်းစတန့်စ် အဖြစ်အသုံးပြုမည် ဆိုပါက၊ ခေါ်ယူခဲ့သော သရဒ် (Thread) အသီးသီးတွင် အသစ်ခေါ်ယူအသုံးပြုမည် ဖြစ်ပါသဖြင့် ဘုံအဖြစ် သရဒ် (Thread) များ အကြားတွင် အသုံးပြုပါရင်လည်း ပြဿနာမရှိပါ။ သို့ရာတွင် ကလပ်စ် ကိန်းရှင်များမှာမူ ကလပ်စ်အား လုဒ်လုပ်သည့်အခါတွင် တစ်ခါတည်းသာ ခေါ်ယူမည် ဖြစ်ပါသဖြင့်၊ သရဒ် များအကြားတွင် ကိန်းရှင်တစ်ခုတည်း ကိုသာ အသုံးပြုမိနေမည် ဖြစ်၏။

ကျွှန်တော်တို့ နမှုနာ ကလပ်စ်တစ်ခုကို shared ထဲတွင် ရေးသားကြည့်ပါမည်။ ရုတ်တရက်ကြည့်လျှင် အင်စတန့်စ် လယ်ဗယ်ဖြင့် အသုံးပြုနေသရောင် မြင်ရမည်ဖြစ်သော်လည်း၊ ကလပ်စ် ကိန်းရှင်ကို အသုံးပြုထားပါသည်။ ထို့အတွက် setText မက်သတ်ကို အသုံးပြုမည် ဆိုပါက ဘုံအနေဖြင့် အသုံးပြုနေသည့် သရဒ်များအား အကျိုးသက်ရောက်မှု့ ပေးနိုင်မည် ဖြစ်၏။ ဤနမှုနာသည် ကိုယ်တိုင် ရေးသား ထားပါသဖြင့် ရှောင်တိမ်းနိုင်မည် ဖြစ်သော်လည်း၊ အခြားသူများက ရေးသားထားသော ကလပ်စ်ဖြစ်ပါက၊ Framework ၏ ကလပ်စ် တစ်ခုဖြစ်ခဲ့ပါက ဘုမသိဘမသိနှင့် အသုံးပြုနေနိုင်ပါသည်။
package shared;

public class Label{
 private static String text="";

 public synchronized void setText(String text){
  this.text=text;
 }

 public String getText(){
  return(text);
 }
}
တဖန် ကလပ်စ်တစ်ခုအား ကလပ်စ်လုဒ်ဒါအမျိုးမျိုးအပေါ်တွင် ထားရှိမိသည့်အခါမျိုးတွင် ပို၍ သတိထားသင့်ပါသည်။ ဥပမာ both.Sample ဟု ကလပ်စ်တစ်ခုကိုရေးပြီး၊ အထက်ပါ Label ကလပ်စ်နှင့် အတူ Shared ကလပ်စ် လုဒ်ဒါက မြင်နိုင်သောနေရာတွင် ထားရှိပါမည်။ တဖန် ထိုကလပ်စ်ကို ဝဘ်အပလီကေးရှင်း တစ်ခုအတွင်းတွင်လည်း ထားကြည့်ပါမည်။ ပြီးလျှင် အောက်ပါ မက်သတ်ကို Label ကလပ်စ် အတွင်းတွင် ဖြည့်စွက်ရေးသားကြည့်ပါမည်။ မည်သည့် အဖြေရရှိမည် ထင်သနည်း။
public boolean classTest() {
 ClassLoader cl = Thread.currentThread().getContextClassLoader();
 Class sampleClass;
 try {
  sampleClass = cl.loadClass("both.Sample");
  return (sampleClass.equals(both.Sample.class));
 } catch (ClassNotFoundException e) {
  e.printStackTrace();
 }
    return false;
}
false ဖြစ်၏။ ရုတ်တရက်ကြည့်မည် ဆိုလျှင်၊ both.Sample ၏ ကလပ်စ်အား နှိုင်းယှဉ်ပြီး၊ တူညီပါက true ကို ပြန်ပေးပြီး၊ မတူညီပါက false ဟု ပြန်ပေးနေ၏။ sampleClass နှင့် both.Sample.class သည် တစ်ခုတည်းသော ကလပ်စ်ဖြစ်ခြင်းကြောင့် တူသရောင်ရောင်ရှိသော်လည်း လုဒ်လုပ်သော လုဒ်ဒါမှာ မတူညီသောကြောင့် false ဟု ပြန်ပေးခြင်း ဖြစ်၏။

ဒုတိယ စာကြောင်းတွင် getContextClassLoader သည် အပလီကေးရှင်း ကလပ်စ် လုဒ်ဒါကို ခေါ်ယူပေးနိုင်ပြီး၊ အဆိုပါ cl ကလပ်စ် လုဒ်ဒါကို အသုံးပြု၍ ခေါ်ယူသော ကလပ်စ်သည် ဝဘ် အပလီကေးရှင်း အတွင်းမှ ကလပ်စ်ကို လုဒ်လုပ်မည်ဖြစ်၏။

တဖန် စာကြောင်း ၄ကြောင်းမြောက်ရှိ both.Sample.class သည် Common ကလပ်စ်လုဒ်ဒါမှ လုဒ်လုပ်ထားသော both.Sample ၏ ကလပ်စ်ကို ပြန်ပေးမည်ဖြစ်၏။ ဤနည်းအားဖြင့် ကလပ်စ် အမည်မှာ တူညီသော်လည်း မံမိုရီအပေါ်ကို ကလပ်စ်လုဒ်ဒါနှစ်ခုဖြင့် ၂ကြိမ်ခေါ်ယူထားသောကြောင့်၊ ကလပ်စ် နှစ်ခုဖြစ်နေပြီး တူသလားဟုမေးသောအခါ မတူပါဟု အဖြေရရှိခြင်း ဖြစ်၏။

ဤနမှုနာတွင် သိပ်ပြီးပြဿနာမရှိသော်လည်း သတိမမှုမိပဲ အသုံးပြုမိပါက မမျှော်လင့်သော အခက်အခဲများနှင့် ကြုံတွေ့တတ်ပါသည်။

ဆာဗလက်သည် မာလတီသရဒ် (Multi Thread) အပလီကေးရှင်းများ ဖြစ်ကြပါသဖြင့်၊ သရဒ်များအကြားတွင် ဘုံကလပ်စ်များအား အသုံးပြုရာတွင်၎င်း၊ ကလစ်လုဒ်ဒါများ၏ သဘောသဘာဝကို နားလည်ပြီး သရဒ်များကြားတွင် ကလပ်စ်များအား ခွဲခြားအသုံးပြုနိုင်ရန်၎င်း စီမံ၍ မာလတီသရဒ်၏ အကျိုးကို ကောင်းစွာအသုံးချသင့်ပါသည်။

ဤအခန်းဖြင့် အီးဇီးဆာဗလက် ခေါင်းစဉ်ကို အဆုံးသတ်ပါမည်။ ရှေ့ဆက်၍ အီးဇီးဂျေအက်စ်ပီ နှင့် အီးဇီးဒေတာဘေစ် အခန်းများကို ဖော်ပြပြီးသည့်နောက်တွင် Struts, Spring အစရှိသည့် အခြေခံ Framework များနှင့် EJB3 ကို အစပြုသော Java EE ကို ဆက်လ က်မိတ်ဆက်ရေးသား သွားပါဦးမည်။


ကိုးကား
http://www.techscore.com/tech/Java/JavaEE/Servlet/supplement-1/


မြန်မာမှုပြုထားသော စကားလုံးများ

  • သရဒ် : Thread
  • မာလတီ သရဒ် : Multi Thread
  • ကလပ်စ် လုဒ်ဒါ : Class Loader

လေးစားစွာဖြင့်
မင်းလွင်

No comments:

Post a Comment