JQuery使用Ajax內存溢出問題總結


最近做一個項目,環境是struts2.3.16,spring3.0,mybatis2.3

當我使用JQuery的ajax方法提交請求返回個對象時,遇到了內存泄露的問題,這個問題困擾了我一個多星期:

開始調用ajax方法,反應比較慢,大概4~5秒之后才會出現效果.

重復幾次調用之后,瀏覽器直接崩潰,系統開始卡,一步一卡...

打開cpu監視情況發現,當調用ajax方法,內存從百分之56直接飛到87..

隨之MyEclipse后台爆出java.lang.OutOfMemoryError: PermGen space...

找了N久..在其他人機器上運行結果一樣...郁悶~馬上要交貨, 查閱很多相關文章,最終確定是自己代碼問題, 與環境無關,仔細將代碼檢查了2遍,沒有發現任何不符合常規的問題....

突然意識到一個問題, 項目使用的是mybatis框架,在Mybatis中配置resultMap是可以配置關聯查詢的..而在傳遞數據是采用Josn格式傳遞.

使用josn需要注意的一個問題就是一定要避免復合結構數據死循環..

比如班級(Classes),學生(Student)兩個類, 在Classes一方有list<Student> students屬性,而在Student中有Classes classess屬性,

他們直接互相存在對方的引用,當使用josn傳遞數據,就會出現無限級查詢的死循環..所傳遞的Josn數據也是異常龐大...

對自己項目中,因為使用的struts2做控制器,所以在使用jquery調用ajax時,我是直接通過struts2集成的josn(偷懶),代碼如下:

ajax,一個動態級聯請求方法:

$('#companySelect').change(function(){
      var deptId=$(this).val();
      var sendData={'deptId':deptId};//數據 josn格式數據
      var url="user!searSecondSelect";//地址
      $.ajax({//寫法是josn格式的 
          url:url,//地址
          data:sendData,//參數
          type:'post',//設置提交類型
          success:function(data){//請求成功的回調函數
              var value='<option value="0">--請選擇部門--</option>';
              for(var i=0;i<data.deptlist.length;i++){
                  value+='<option value="'+data.deptlist[i].deptId+'">'+data.deptlist[i].deptName+'</option>'
              }
              $('#deptIdSelect').html(value);
          }
      });
});

 

請求方法代碼: 通過查詢數據庫,將結果放入相應的封裝好屬性中(deptlist). 

public String searSecondSelect(){
       this.setDeptlist(ds.selectAll(deptId));
       return "searchTwoDept";
}

 

struts.xml配置:通過繼承json-default包來傳遞josn數據

<package name="zhanglu" namespace="/" extends="json-default">
        <action name="user" class="userAction">
            <result name="success">/Permission/user_manage.jsp</result>
            <result name="exits">/Permission/Exits.jsp</result>
            <result name="postInfo" type="json"></result>
            <result name="searchTwoDept" type="json"></result>
        </action>
</package >

 

整個ajax請求到回調函數,沒有任何問題,運行一切ok..

可是在另一個ajax方法中就出現內存溢出,我需要查詢一個員工信息對象(employee)返回在頁面顯示,試過很多的方法, 最終決定換一種josn傳遞方式,不使用struts2的json-default方式,另一種寫法如下:

 

ajax方法.請求一個方法,查詢empInfo信息, 其中empAnnexInfos為其他類引用對象

var sendData = { 'userName' : userName};//數據 josn格式數據
var url = "user!searchEmpInfo";//地址
$.ajax({//注意寫法是josn格式的  推薦使用ajax  原因是速度快
       url : url,//地址
       data : sendData,//參數
       type : 'post',//設置提交類型
       success : function(data) {//請求成功的回調函數
         var emps=eval(data);
         $(emps).each(function (i, emp) {
                var empAnn=eval(emp.empAnnexInfos);
                  $(empAnn).each(function (i, ema){
                    var img='<img src="'+ema.empHead+'" width="120" height="200"/>';
                    $('#empInfo .images').html(img);
               });
             var empInfo='姓 名:'+emp.empName+'<hr/>聯系電話:'+emp.empMobilePhone+'<hr/>聯系郵箱:'+emp.empEmail+'<hr/>家庭住址:'+emp.empAddress+'<hr/>目前薪資:'+emp.empSalary;
             empInfo+='<hr/>入職時間'+emp.emTime;
             $('#empInfo .einfo').html(empInfo);
           });
       }
});

 

action方法:

public void searchEmpInfo() throws Exception{
        String name=this.getUserName().trim();
        this.setEmpInfo(emd.getEmpInfoByEmpNum(name));
        if(empInfo.getEmpAnnexInfos()==null){
            System.out.println("annexinfo is null");
        }
        PrintWriter out=this.getResponse().getWriter();   
        JsonConfig cfg = new JsonConfig();
        JSONArray jsonList=JSONArray.fromObject(empInfo,cfg);
     System.out.println(jsonList.toString());//輸出josn數據字符串 out.print(jsonList.toString()); }

如果使用PrintWriter就不需要配置struts.xml

 

最終運行結果,依然是內存溢出,當我吧控制台輸出的josn字符串復制到sublimeText中查看時, 出現了一個嚇人的結果:

 

密密麻麻N長一片,仔細看,這些亂七八糟的數據,就是Josn..我想這就是內存溢出的真正原因了,雖然employee對象本身並不大,而在EmployeeInfo.java中卻引用了其他7個實體類的引用,7個實體類同樣引用了EmployeeInfo對象,這下糾結了...毫無疑問直接傳遞員工對象Josn陷入死循環就是內存溢出的根本原因所在...

網上查了一下能將josn去掉關聯的方法:

參考:http://www.2cto.com/kf/201303/198961.html的方法

修改上面的action方法:

public void searchEmpInfo() throws Exception{
        String name=this.getUserName().trim();
        this.setEmpInfo(emd.getEmpInfoByEmpNum(name));
        if(empInfo.getEmpAnnexInfos()==null){
            System.out.println("annexinfo is null");
        }
        PrintWriter out=this.getResponse().getWriter();   
        JsonConfig cfg = new JsonConfig();
        cfg.setExcludes(new String[]{"employeeInfo","borders","workOverTimes","askForLeaveEaas","compacts","goOnErrandses","empBoons","udops","replacingPosts","transferEmps","rewardPunishments","timeBooks","post"});
        JSONArray jsonList=JSONArray.fromObject(empInfo,cfg);

System.out.println(jsonList.toString());//輸出josn數據字符串
        out.print(jsonList.toString()); 
}

 

這一次查看josn字符串,過濾成功,如圖:

 

頁面運行效果:

 

內存溢出終於解決.....

該好好睡覺了.... 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM