posts - 42,comments - 83,trackbacks - 0
                  這兩天有客戶(hù)跟我說(shuō)了個(gè)問(wèn)題,說(shuō)他們發(fā)現(xiàn)weblogic不停的load class,最后線(xiàn)程都掛在了Zip Entry操作上。讓他們做了thread dump, 開(kāi)始以為跟JDK的IO性能有關(guān)系,因?yàn)槲以?jīng)在HP\AIX上都碰到過(guò)線(xiàn)程掛起在zip操作上的問(wèn)題,最終客戶(hù)通過(guò)調(diào)整OS參數(shù)后,問(wèn)題得到解決。但在拿到thread dump后, 發(fā)現(xiàn)問(wèn)題不是他們說(shuō)的那樣,thread trace如下:

          "ExecuteThread: '6' for queue: 'Out.Thread Pool'" daemon prio=5 tid=0005ff90 nid=54 lwp_id=1885955 waiting for monitor entry [0x239fa000..0x239f94f0]
           at java.util.zip.ZipFile.getEntry(ZipFile.java:161)
           - waiting to lock <35da8e78> (a sun.net.www.protocol.jar.URLJarFile)
           at java.util.jar.JarFile.getEntry(JarFile.java:194)
           at sun.net.www.protocol.jar.URLJarFile.getEntry(URLJarFile.java:89)
           at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:95)
           at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:107)
           at java.net.URL.openStream(URL.java:913)
           at java.lang.ClassLoader.getResourceAsStream(ClassLoader.java:997)
           at javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:160)
           at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:87)
           at org.dom4j.io.JAXPHelper.createXMLReader(JAXPHelper.java:46)
           at org.dom4j.io.SAXHelper.createXMLReaderViaJAXP(SAXHelper.java:125)
           at org.dom4j.io.SAXHelper.createXMLReader(SAXHelper.java:78)
           at org.dom4j.io.SAXReader.createXMLReader(SAXReader.java:894)
           at org.dom4j.io.SAXReader.getXMLReader(SAXReader.java:715)
           at org.dom4j.io.SAXReader.read(SAXReader.java:435)
           at org.dom4j.DocumentHelper.parseText(DocumentHelper.java:278)
           ......

                  我們可以看看SAXParserFactory.newInstance()的實(shí)現(xiàn),

           1     public static SAXParserFactory newInstance()
           2         throws FactoryConfigurationError
           3     {
           4         try
           5         {
           6             return (SAXParserFactory)FactoryFinder.find("javax.xml.parsers.SAXParserFactory""org.apache.xerces.jaxp.SAXParserFactoryImpl");
           7         }
           8         catch(FactoryFinder.ConfigurationError configurationerror)
           9         {
          10             throw new FactoryConfigurationError(configurationerror.getException(), configurationerror.getMessage());
          11         }
          12     }

                  再來(lái)看看FactoryFinder.find()的實(shí)現(xiàn),

           1     static Object find(String s, String s1)
           2         throws ConfigurationError
           3     {
           4         debugPrintln("debug is on");
           5         ClassLoader classloader = findClassLoader();
           6         try
           7         {
           8             String s2 = System.getProperty(s);
           9             if(s2 != null)
          10             {
          11                 debugPrintln("found system property " + s2);
          12                 return newInstance(s2, classloader);
          13             }
          14         }
          15         catch(SecurityException _ex) { }
          16         try
          17         {
          18             String s3 = System.getProperty("java.home");
          19             String s5 = s3 + File.separator + "lib" + File.separator + "jaxp.properties";
          20             File file = new File(s5);
          21             if(file.exists())
          22             {
          23                 Properties properties = new Properties();
          24                 properties.load(new FileInputStream(file));
          25                 String s7 = properties.getProperty(s);
          26                 debugPrintln("found java.home property " + s7);
          27                 return newInstance(s7, classloader);
          28             }
          29         }
          30         catch(Exception exception) { }
          31         String s4 = "META-INF/services/" + s;
          32         try
          33         {
          34             java.io.InputStream inputstream = null;
          35             if(classloader == null)
          36                 inputstream = ClassLoader.getSystemResourceAsStream(s4);
          37             else
          38                 inputstream = classloader.getResourceAsStream(s4);
          39             if(inputstream != null)
          40             {
          41                 debugPrintln("found " + s4);
          42                 BufferedReader bufferedreader;
          43                 try
          44                 {
          45                     bufferedreader = new BufferedReader(new InputStreamReader(inputstream, "UTF-8"));
          46                 }
          47                 catch(UnsupportedEncodingException _ex)
          48                 {
          49                     bufferedreader = new BufferedReader(new InputStreamReader(inputstream));
          50                 }
          51                 String s6 = bufferedreader.readLine();
          52                 bufferedreader.close();
          53                 if(s6 != null && !"".equals(s6))
          54                 {
          55                     debugPrintln("loaded from services: " + s6);
          56                     return newInstance(s6, classloader);
          57                 }
          58             }
          59         }
          60         catch(Exception exception1) { }
          61         if(s1 == null)
          62         {
          63             throw new ConfigurationError("Provider for " + s + " cannot be found"null);
          64         } else
          65         {
          66             debugPrintln("loaded from fallback value: " + s1);
          67             return newInstance(s1, classloader);
          68         }
          69     }
          70 

                  看看兩個(gè)方法的具體實(shí)現(xiàn),這個(gè)問(wèn)題基本一目了然了吧。 在我們要解析XML文件的時(shí)候,我們首先需要從parser factory獲取一個(gè)parser實(shí)例,但parser factroy是什么? 我們需要去查找。仔細(xì)看一下這個(gè)查找順序:
          1:System property, JVM中是否定義了javax.xml.parsers.SAXParserFactory,這個(gè)可以通過(guò)-D設(shè)定
          2:$JRE_HOME/ lib/jaxp.properties文件,是否存在javax.xml.parsers.SAXParserFactory鍵值對(duì)
          3:xerces.jar文件的meta-inf/services/javax.xml.parsers.SAXParserFactory文件是否有值
          4:當(dāng)前classloader,是否存在org.apache.xerces.jaxp.SAXParserFactoryImpl,

                  從thread dump可以看到,客戶(hù)線(xiàn)程掛在了3上,因?yàn)?, 2條件不成立,所以走到了3, 而3每次都要打開(kāi)jar文件,最終看到線(xiàn)程都停在了java.util.zip.ZipFile.getEntry()上。 解決方法:
          1:?jiǎn)?dòng)JVM的時(shí)候,增加-Djavax.xml.parsers.SAXParserFactory=***
          2::在$JRE_HOME/lib/增加jaxp.properties文件,其中定義javax.xml.parsers.SAXParserFactory=***
          3:用展開(kāi)的xerces.jar文件代替原有的jar文件

                  客戶(hù)同時(shí)提及了另外一個(gè)問(wèn)題:我們有自己的parser factory, 為什么最后用了weblogic的? 而且不停的load class? Trace 如下:

          "ExecuteThread: '42' for queue: 'OCS.Thread.Pool'" daemon prio=5 tid=004ca430 nid=245 lwp_id=1886146 waiting for monitor entry [0x1d9ba000..0x1d9ba4f0]
           at java.lang.ClassLoader.loadClass(ClassLoader.java:278)
           - waiting to lock <364cdf18> (a weblogic.utils.classloaders.GenericClassLoader)
           at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
           at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:224)
           at javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:93)
           at javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:174)
           ......

                  其實(shí)在上面的分析中可以看到,前三項(xiàng)中都沒(méi)有找到parser factory, 那我們只能在當(dāng)前class loader中去查找,并創(chuàng)建instance。因?yàn)槟愕膽?yīng)用部署在weblogic上, weblogic的classloader機(jī)制是, 所有的應(yīng)用class loader都繼承于weblogic application class loader, 所以你會(huì)看到weblogic class loader在trace中。但為什么不停的在class loader呢?其實(shí)看看JDK文檔,并看看JDK的實(shí)現(xiàn)就能知道,
          protected Class<?> loadClass(String name,
          boolean resolve)
          throws ClassNotFoundException
          Loads the class with the specified binary name. The default implementation of this method searches for classes in the following order:

           

          1. Invoke findLoadedClass(String) to check if the class has already been loaded.

          2. Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.

          3. Invoke the findClass(String) method to find the class.

          If the class was found using the above steps, and the resolve flag is true, this method will then invoke the resolveClass(Class) method on the resulting Class object.



           1     protected synchronized Class loadClass(String name, boolean resolve)
           2     throws ClassNotFoundException
           3     {
           4     // First, check if the class has already been loaded
           5     Class c = findLoadedClass(name);
           6     if (c == null) {
           7         try {
           8         if (parent != null) {
           9             c = parent.loadClass(name, false);
          10         } else {
          11             c = findBootstrapClass0(name);
          12         }
          13         } catch (ClassNotFoundException e) {
          14             // If still not found, then invoke findClass in order
          15             // to find the class.
          16             c = findClass(name);
          17         }
          18     }
          19     if (resolve) {
          20         resolveClass(c);
          21     }
          22     return c;
          23     }

                  看看,其實(shí)能看到loadclass(),并不能說(shuō)class loader一定在load class,更多的時(shí)候,他們是在find loaded class,否則怎么去創(chuàng)建對(duì)象?







          posted on 2008-09-13 21:57 走走停停又三年 閱讀(2969) 評(píng)論(1)  編輯  收藏 所屬分類(lèi): Weblogic

          FeedBack:
          # re: 關(guān)于weblogic中使用Dom4j、Xerces導(dǎo)致執(zhí)行線(xiàn)程掛起的問(wèn)題
          2011-09-21 15:44 | ,,,
          主站蜘蛛池模板: 南郑县| 克什克腾旗| 泰和县| 贵港市| 岳阳市| 肇东市| 城口县| 德令哈市| 枝江市| 扎囊县| 庆阳市| 扬中市| 太和县| 龙江县| 晋城| 特克斯县| 两当县| 灌阳县| 宁乡县| 东明县| 抚宁县| 崇信县| 县级市| 濮阳县| 清水河县| 司法| 沁阳市| 晋州市| 桓台县| 沙湾县| 泰顺县| 勐海县| 仪征市| 渝中区| 昌黎县| 灌南县| 赣榆县| 舞钢市| 玉山县| 龙南县| 呼伦贝尔市|