Problem
Attached is an example application to demonstrate memory leak by Http Client.
Making multiple webservice call but still heap memory keep on increasing and app leads to "Out Of Memory Exception" if heap memory exceeds size limit leading app to potentially crash.
Monitoring app through out iOS Instruments revealed no HTTP Client objects remain stacked up in memory.
Steps to reproduce
The following steps attempt to demonstrate the issue with suds.js sample.
1. Run sample code
2. Click on "Start Web Service Call" Button.
3. App starts making multiple requests using http client suds.js
4. Start analysing Deprecated Logcat and filter with the keyword "Heap" as provided the screen shot at the jira ticket.
5. Once app Heap memory crosses certain limit you will see whether an error or crash on the app screen Location: suds.js
6. Analyses the error using log cat : Out of Memory Exception. Try repeating the above steps more than once, you will see the error.
Stack trace
Droid Razr 2.3.5 OS
1st run
11-05 16:14:12.964: I/dalvikvm-heap(4781): Grow heap (frag case) to 15.250MB for 1554748-byte allocation
11-05 16:14:13.058: I/dalvikvm-heap(4781): Grow heap (frag case) to 16.715MB for 1351190-byte allocation
11-05 16:14:21.035: I/dalvikvm-heap(4781): Grow heap (frag case) to 17.131MB for 1175574-byte allocation
11-05 16:14:54.988: I/dalvikvm-heap(4781): Grow heap (frag case) to 15.909MB for 3707168-byte allocation
11-05 16:14:55.097: I/dalvikvm-heap(4781): Grow heap (frag case) to 16.792MB for 2780384-byte allocation
11-05 16:14:55.222: I/dalvikvm-heap(4781): Grow heap (frag case) to 14.583MB for 2780384-byte allocation
11-05 16:14:56.097: I/dalvikvm-heap(4781): Grow heap (frag case) to 18.973MB for 2719000-byte allocation
11-05 16:14:56.199: I/dalvikvm-heap(4781): Grow heap (frag case) to 21.133MB for 4078496-byte allocation
11-05 16:14:56.277: I/dalvikvm-heap(4781): Grow heap (frag case) to 21.186MB for 2777424-byte allocation
11-05 16:15:45.222: I/dalvikvm(2526): dvmDdmHandleHpsgChunk(when 1, what 0, heap 0)
11-05 16:15:53.863: D/ddm-heap(2526): Heap GC request
11-05 16:18:04.747: I/dalvikvm-heap(4781): Grow heap (frag case) to 16.023MB for 3707168-byte allocation
11-05 16:18:04.856: I/dalvikvm-heap(4781): Grow heap (frag case) to 16.907MB for 2780384-byte allocation
11-05 16:18:04.981: I/dalvikvm-heap(4781): Grow heap (frag case) to 14.697MB for 2780384-byte allocation
11-05 16:18:05.849: I/dalvikvm-heap(4781): Grow heap (frag case) to 19.086MB for 2719000-byte allocation
11-05 16:18:05.942: I/dalvikvm-heap(4781): Grow heap (frag case) to 21.247MB for 4078496-byte allocation
11-05 16:18:06.044: I/dalvikvm-heap(4781): Grow heap (frag case) to 21.299MB for 2777424-byte allocation
11-05 16:18:06.419: D/GraphicsJNI(4781): Waiting for heap walker to free more memory
11-05 16:18:06.442: D/GraphicsJNI(4781): Heap walker done, retry to allocate
11-05 16:18:07.177: I/dalvikvm-heap(499): Grow heap (frag case) to 21.693MB for 60840-byte allocation
11-05 16:18:07.356: I/dalvikvm-heap(499): Grow heap (frag case) to 19.512MB for 121664-byte allocation
11-05 16:18:07.513: I/dalvikvm-heap(499): Grow heap (frag case) to 19.571MB for 60840-byte allocation
2nd run
11-05 16:29:50.856: I/dalvikvm(6859): dvmDdmHandleHpsgChunk(when 1, what 0, heap 0)
11-05 16:29:55.981: D/ddm-heap(6859): Heap GC request
11-05 16:30:08.481: I/dalvikvm-heap(6859): Grow heap (frag case) to 9.940MB for 668897-byte allocation
11-05 16:30:08.638: I/dalvikvm-heap(6859): Grow heap (frag case) to 10.571MB for 668897-byte allocation
11-05 16:30:08.763: I/dalvikvm-heap(6859): Grow heap (frag case) to 11.208MB for 891856-byte allocation
11-05 16:30:08.872: I/dalvikvm-heap(6859): Grow heap (frag case) to 11.634MB for 445936-byte allocation
11-05 16:30:08.997: I/dalvikvm-heap(6859): Grow heap (frag case) to 12.511MB for 1783696-byte allocation
11-05 16:30:09.114: I/dalvikvm-heap(6859): Grow heap (frag case) to 13.362MB for 891856-byte allocation
11-05 16:30:09.935: I/dalvikvm-heap(6859): Grow heap (frag case) to 14.082MB for 1357688-byte allocation
11-05 16:30:17.200: I/dalvikvm-heap(6859): Grow heap (frag case) to 15.623MB for 760710-byte allocation
11-05 16:31:06.060: I/dalvikvm-heap(6859): Grow heap (frag case) to 15.256MB for 1554748-byte allocation
11-05 16:31:10.419: D/ddm-heap(6859): Heap GC request
11-05 16:31:23.341: D/ddm-heap(6859): Heap GC request
11-05 16:31:31.669: I/dalvikvm-heap(6859): Grow heap (frag case) to 15.923MB for 3707168-byte allocation
11-05 16:31:31.856: I/dalvikvm-heap(6859): Grow heap (frag case) to 16.807MB for 2780384-byte allocation
11-05 16:31:32.052: I/dalvikvm-heap(6859): Grow heap (frag case) to 14.597MB for 2780384-byte allocation
11-05 16:31:33.091: I/dalvikvm-heap(6859): Grow heap (frag case) to 18.987MB for 2719000-byte allocation
11-05 16:31:33.271: I/dalvikvm-heap(6859): Grow heap (frag case) to 21.147MB for 4078496-byte allocation
11-05 16:31:33.442: I/dalvikvm-heap(6859): Grow heap (frag case) to 21.201MB for 2777424-byte allocation
3rd run
11-05 16:50:45.906: E/dalvikvm-heap(8253): Out of memory on a 1024256-byte allocation.
11-05 16:50:45.906: I/dalvikvm(8253): "KrollRuntimeThread" prio=5 tid=10 RUNNABLE
11-05 16:50:45.906: I/dalvikvm(8253): | group="main" sCount=0 dsCount=0 obj=0x405a6480 self=0x2dc020
11-05 16:50:45.906: I/dalvikvm(8253): | sysTid=8263 nice=0 sched=0/0 cgrp=default handle=2998616
11-05 16:50:45.906: I/dalvikvm(8253): | schedstat=( 81520599501 5353912207 33230 )
11-05 16:50:45.906: I/dalvikvm(8253): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:~95)
11-05 16:50:45.906: I/dalvikvm(8253): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:153)
11-05 16:50:45.906: I/dalvikvm(8253): at java.lang.StringBuilder.append(StringBuilder.java:217)
11-05 16:50:45.906: I/dalvikvm(8253): at ti.modules.titanium.xml.ElementProxy.getTextImpl(ElementProxy.java:59)
11-05 16:50:45.906: I/dalvikvm(8253): at ti.modules.titanium.xml.ElementProxy.getTextImpl(ElementProxy.java:64)
11-05 16:50:45.906: I/dalvikvm(8253): at ti.modules.titanium.xml.ElementProxy.getTextContent(ElementProxy.java:47)
11-05 16:50:45.906: I/dalvikvm(8253): at ti.modules.titanium.xml.ElementProxy.getText(ElementProxy.java:40)
11-05 16:50:45.906: I/dalvikvm(8253): at org.appcelerator.kroll.runtime.v8.V8Object.nativeCallProperty(Native Method)
11-05 16:50:45.906: I/dalvikvm(8253): at org.appcelerator.kroll.runtime.v8.V8Object.callProperty(V8Object.java:63)
11-05 16:50:45.906: I/dalvikvm(8253): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:869)
11-05 16:50:45.906: I/dalvikvm(8253): at android.os.Handler.dispatchMessage(Handler.java:95)
11-05 16:50:45.906: I/dalvikvm(8253): at android.os.Looper.loop(Looper.java:130)
11-05 16:50:45.906: I/dalvikvm(8253): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112)
11-05 16:50:45.914: W/System.err(8253): java.lang.OutOfMemoryError
11-05 16:50:45.914: W/System.err(8253): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
11-05 16:50:45.914: W/System.err(8253): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:153)
11-05 16:50:45.914: W/System.err(8253): at java.lang.StringBuilder.append(StringBuilder.java:217)
11-05 16:50:45.914: W/System.err(8253): at ti.modules.titanium.xml.ElementProxy.getTextImpl(ElementProxy.java:59)
11-05 16:50:45.914: W/System.err(8253): at ti.modules.titanium.xml.ElementProxy.getTextImpl(ElementProxy.java:64)
11-05 16:50:45.914: W/System.err(8253): at ti.modules.titanium.xml.ElementProxy.getTextContent(ElementProxy.java:47)
11-05 16:50:45.914: W/System.err(8253): at ti.modules.titanium.xml.ElementProxy.getText(ElementProxy.java:40)
11-05 16:50:45.914: W/System.err(8253): at org.appcelerator.kroll.runtime.v8.V8Object.nativeCallProperty(Native Method)
11-05 16:50:45.914: W/System.err(8253): at org.appcelerator.kroll.runtime.v8.V8Object.callProperty(V8Object.java:63)
11-05 16:50:45.914: W/System.err(8253): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:869)
11-05 16:50:45.914: W/System.err(8253): at android.os.Handler.dispatchMessage(Handler.java:95)
11-05 16:50:45.914: W/System.err(8253): at android.os.Looper.loop(Looper.java:130)
11-05 16:50:45.914: W/System.err(8253): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112)
11-05 16:50:45.914: I/DEBUG(9126): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-05 16:50:45.914: I/DEBUG(9126): Build fingerprint: 'verizon/spyder_vzw/cdma_spyder:2.3.5/6.5.1-73_DHD-11_M1-2/111130:user/release-keys'
11-05 16:50:45.914: I/DEBUG(9126): pid: 8253, tid: 8263 >>> com.appc.test <<<
11-05 16:50:45.914: I/DEBUG(9126): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
11-05 16:50:45.914: I/DEBUG(9126): tls: 44e14f00
11-05 16:50:45.914: I/DEBUG(9126): r0 002cc168 r1 44e14ac7 r2 00000008 r3 00000001
11-05 16:50:45.914: I/DEBUG(9126): r4 8253f1e0 r5 00001e40 r6 00000000 r7 00000000
11-05 16:50:45.914: I/DEBUG(9126): r8 44e14ac7 r9 00000000 10 002fd964 fp 405ed750
11-05 16:50:45.914: I/DEBUG(9126): ip 8253f2c0 sp 44e14a58 lr 8213cf24 pc 8213cf90 cpsr 60000010
11-05 16:50:45.914: I/DEBUG(9126): d0 0074006e00750052 d1 002e0065006d0069
11-05 16:50:45.914: I/DEBUG(9126): d2 006100760061006a d3 003200310031003a
11-05 16:50:45.914: I/DEBUG(9126): d4 480c34d6014dfc48 d5 4069000000000000
11-05 16:50:45.914: I/DEBUG(9126): d6 0000960100000000 d7 0000960100000000
11-05 16:50:45.914: I/DEBUG(9126): d8 0000000041880000 d9 0000000000000000
11-05 16:50:45.914: I/DEBUG(9126): d10 0000000000000000 d11 0000000000000000
11-05 16:50:45.914: I/DEBUG(9126): d12 0000000000000000 d13 0000000000000000
11-05 16:50:45.914: I/DEBUG(9126): d14 0000000000000000 d15 0000000000000000
11-05 16:50:45.914: I/DEBUG(9126): d16 0000000700000000 d17 0000000000000000
11-05 16:50:45.914: I/DEBUG(9126): d18 4042800000000000 d19 0000000000000000
11-05 16:50:45.914: I/DEBUG(9126): d20 3ff0000000000000 d21 8000000000000000
11-05 16:50:45.922: I/DEBUG(9126): d22 c042800000000000 d23 0b00000000000000
11-05 16:50:45.922: I/DEBUG(9126): d24 0800000000000000 d25 0c00000000000000
11-05 16:50:45.922: I/DEBUG(9126): d26 0100010001000100 d27 0100010001000100
11-05 16:50:45.922: I/DEBUG(9126): d28 0100010001000100 d29 3ff0000000000000
11-05 16:50:45.922: I/DEBUG(9126): d30 0000000000000000 d31 3ff0000000000000
11-05 16:50:45.922: I/DEBUG(9126): scr 60000013
11-05 16:50:45.968: I/DEBUG(9126): #00 pc 0013cf90 /data/data/com.appc.test/lib/libkroll-v8.so
11-05 16:50:45.968: I/DEBUG(9126): #01 lr 8213cf24 /data/data/com.appc.test/lib/libkroll-v8.so
11-05 16:50:45.968: I/DEBUG(9126): code around pc:
11-05 16:50:45.968: I/DEBUG(9126): 8213cf70 e12fff33 e3a00000 e8bd8070 e59f3070
11-05 16:50:45.968: I/DEBUG(9126): 8213cf80 e7943003 e5d33000 e3530000 1affffec
11-05 16:50:45.968: I/DEBUG(9126): 8213cf90 e5963000 e3130001 03a00001 08bd8070
11-05 16:50:45.968: I/DEBUG(9126): 8213cfa0 e2032003 e3520001 13a00000 18bd8070
11-05 16:50:45.968: I/DEBUG(9126): 8213cfb0 e5133001 e5d30007 e3500084 13a00000
11-05 16:50:45.968: I/DEBUG(9126): code around lr:
11-05 16:50:45.968: I/DEBUG(9126): 8213cf04 e92d4070 e59f40cc e59f50cc e08f4004
11-05 16:50:45.968: I/DEBUG(9126): 8213cf14 e7943005 e1a06000 e5930000 eb053954
11-05 16:50:45.968: I/DEBUG(9126): 8213cf24 e5903000 e3530001 0a000017 e59f30ac
11-05 16:50:45.968: I/DEBUG(9126): 8213cf34 e7943003 e5d33000 e3530000 0a00000d
11-05 16:50:45.968: I/DEBUG(9126): 8213cf44 e7943005 e5930000 eb053949 e59f2090
11-05 16:50:45.968: I/DEBUG(9126): stack:
11-05 16:50:45.968: I/DEBUG(9126): 44e14a18 002fe958
11-05 16:50:45.968: I/DEBUG(9126): 44e14a1c 00002714
11-05 16:50:45.968: I/DEBUG(9126): 44e14a20 002cc1c0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a24 00000001
11-05 16:50:45.968: I/DEBUG(9126): 44e14a28 00337748
11-05 16:50:45.968: I/DEBUG(9126): 44e14a2c 002cc168
11-05 16:50:45.968: I/DEBUG(9126): 44e14a30 405ed840
11-05 16:50:45.968: I/DEBUG(9126): 44e14a34 aca45399 /system/lib/libdvm.so
11-05 16:50:45.968: I/DEBUG(9126): 44e14a38 002fd974
11-05 16:50:45.968: I/DEBUG(9126): 44e14a3c 00000000
11-05 16:50:45.968: I/DEBUG(9126): 44e14a40 00000000
11-05 16:50:45.968: I/DEBUG(9126): 44e14a44 82072cf9 /data/data/com.appc.test/lib/libkroll-v8.so
11-05 16:50:45.968: I/DEBUG(9126): 44e14a48 002dc9a0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a4c 82073cd3 /data/data/com.appc.test/lib/libkroll-v8.so
11-05 16:50:45.968: I/DEBUG(9126): 44e14a50 df002777
11-05 16:50:45.968: I/DEBUG(9126): 44e14a54 e3a070ad
11-05 16:50:45.968: I/DEBUG(9126): #00 44e14a58 8253f1e0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a5c 002dc9a0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a60 00000000
11-05 16:50:45.968: I/DEBUG(9126): 44e14a64 82073671 /data/data/com.appc.test/lib/libkroll-v8.so
11-05 16:50:45.968: I/DEBUG(9126): 44e14a68 00337748
11-05 16:50:45.968: I/DEBUG(9126): 44e14a6c 0000a000
11-05 16:50:45.968: I/DEBUG(9126): 44e14a70 00337748
11-05 16:50:45.968: I/DEBUG(9126): 44e14a74 00000000
11-05 16:50:45.968: I/DEBUG(9126): 44e14a78 002fd964
11-05 16:50:45.968: I/DEBUG(9126): 44e14a7c afd138af /system/lib/libc.so
11-05 16:50:45.968: I/DEBUG(9126): 44e14a80 8253f1e0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a84 44e14ab0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a88 000013f8
11-05 16:50:45.968: I/DEBUG(9126): 44e14a8c 8253f1e0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a90 44e14ab0
11-05 16:50:45.968: I/DEBUG(9126): 44e14a94 000013f8
11-05 16:50:45.976: I/DEBUG(9126): 44e14a98 00000000
11-05 16:50:45.976: I/DEBUG(9126): 44e14a9c 00337748
11-05 16:50:47.086: D/dalvikvm(1855): GC_EXPLICIT freed 2K, 51% free 3520K/7175K, external 2357K/2773K, paused 35ms
11-05 16:50:48.398: I/DEBUG(9126): debuggerd committing suicide to free the zombie!
11-05 16:50:48.398: I/BootReceiver(499): Copying /data/tombstones/tombstone_06 to DropBox (SYSTEM_TOMBSTONE)
11-05 16:50:48.429: E/InputDispatcher(499): channel '40b8b510 com.appc.test/com.appc.test._1bestpracticesActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x8
11-05 16:50:48.429: E/InputDispatcher(499): channel '40b8b510 com.appc.test/com.appc.test._1bestpracticesActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
11-05 16:50:48.429: D/Zygote(275): Process 8253 terminated by signal (11)
11-05 16:50:48.484: D/dalvikvm(499): GC_FOR_MALLOC freed 931K, 30% free 10108K/14407K, external 8158K/10188K, paused 89ms
11-05 16:50:48.484: I/dalvikvm-heap(499): Grow heap (frag case) to 20.005MB for 87396-byte allocation
11-05 16:50:48.570: D/dalvikvm(499): GC_FOR_MALLOC freed <1K, 30% free 10193K/14535K, external 8158K/10188K, paused 75ms
11-05 16:50:48.570: I/WindowManager(499): WINDOW DIED Window{40b8b510 com.appc.test/com.appc.test._1bestpracticesActivity paused=false}
11-05 16:50:48.570: I/ActivityManager(499): Process com.appc.test (pid 8253) has died.
11-05 16:50:48.578: W/WindowManager(499): Failed looking up window
11-05 16:50:48.578: W/WindowManager(499): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@40b258a8 does not exist
11-05 16:50:48.578: W/WindowManager(499): at com.android.server.WindowManagerService.windowForClientLocked(WindowManagerService.java:8590)
11-05 16:50:48.578: W/WindowManager(499): at com.android.server.WindowManagerService.windowForClientLocked(WindowManagerService.java:8581)
11-05 16:50:48.578: W/WindowManager(499): at com.android.server.WindowManagerService$WindowState$DeathRecipient.binderDied(WindowManagerService.java:7440)
11-05 16:50:48.578: W/WindowManager(499): at android.os.BinderProxy.sendDeathNotice(Binder.java:397)
11-05 16:50:48.578: W/WindowManager(499): at dalvik.system.NativeStart.run(Native Method)
11-05 16:50:48.578: I/WindowManager(499): WIN DEATH: null
Repro sequence
app.js
Ti.include('suds.js');
var webServiceMethod = ["GetItemsList", "GetUOMList", "GetItemPriceList", "GetBankList", "GetBillReferanceList", "GetCategoryList", "GetPayTermsList", "GetPayModeList", "GetReasonList", "GetPriceGroupList", "GetCustomerAgentList", "GetServiceMasterList", "GetCurrencyUnitList", "GetCustomerProductList", "GetVanInventoryNew", "GetAgentListNew", "GetCreditNoteList", "GetCreditNoteItemsList", "GetInvoicesList", "GetInvoiceItemsList", "GetRouteMasterList", "GetRouteDetailsList", "GetSystemTable", "GetLocationList", "GetOrderHeaderList", "GetOrderItemsList", "GetCustomersList"];
var APIStatus = [];
var win = Titanium.UI.createWindow({
title:'Sample Web Service Call',
backgroundColor:'#000'
});
var label = Titanium.UI.createLabel({
color:'#fff',
text:'Titanium HTTPClient Heap Memory Deallocation Issue Example',
font:{fontSize:20,fontFamily:'Helvetica Neue'},
textAlign:'center',
width:'auto',
top:'5%'
});
label.addEventListener('click',function(){
WebserviceStart()
});
var button = Titanium.UI.createButton({
title : "Start WebService Call",
width : '50%',
height : 60,
borderRadius : 6,
top:'10%'
});
button.addEventListener('click',function(){
WebserviceStart()
});
var actInd = Titanium.UI.createActivityIndicator({
font : {
fontFamily : 'Helvetica Neue',
fontSize : 30,
fontWeight : 'bold'
},
color : 'white',
message : 'Loading...',
height : win.height,
width : win.width,
zIndex : 50
});
var suds = new SudsClient({
endpoint : "http://meijiservice.cloudapp.net/Service.asmx",
targetNamespace : "http://tempuri.org"
});
win.add(label);
win.add(button);
win.add(actInd);
win.open();
function WebserviceStart(){
var date = new Date();
Ti.API.info("START TIME: " + date);
var obj = {};
APIStatus = [];
obj.start = 0;
obj.end = 2000;
obj.action = webServiceMethod[0];
actInd.show();
webServiceCall(obj);
}
function webServiceCall(obj){
obj.callparams = {
offset: obj.start,
length: obj.end,
mdtNo: "TAB015"
};
suds.invoke(obj.action, obj.callparams, function(xmlDoc, httpStatus) {
var results = xmlDoc.documentElement.getElementsByTagName(obj.action+'Response');
var result = results.item(0).text;
var data = JSON.parse("["+result+"]");
var totalLength = data[0].TotalLength[0].TotalLength;
var totalAddedRecord = (parseInt(data[0].TotalLength[0].Length)+parseInt(data[0].TotalLength[0].Offset));
Ti.API.info("Action:"+ obj.action +" TotalLength:"+totalLength+" Start:"+ (totalAddedRecord-2000) + "End:"+totalAddedRecord);
if(totalLength==0 || totalLength<totalAddedRecord){
if(APIStatus.indexOf(obj.action)<0){
APIStatus.push(obj.action);
}
if(APIStatus.length == webServiceMethod.length){
var date = new Date();
Ti.API.info("END TIME: " + date);
alert("WEB SERVICE COMPLETED");
actInd.hide();
}else{
obj.action = webServiceMethod[APIStatus.length];
obj.start = 0;
obj.end = 2000;
webServiceCall(obj);
}
}else{
obj.start = totalAddedRecord;
obj.end = 2000;
webServiceCall(obj);
}
});
}
suds.js
/**
* Suds: A Lightweight JavaScript SOAP Client
* Copyright: 2009 Kevin Whinnery (http://www.kevinwhinnery.com)
* License: http://www.apache.org/licenses/LICENSE-2.0.html
* Source: http://github.com/kwhinnery/Suds
*/
function SudsClient(_options) {
function isBrowserEnvironment() {
try {
if (window && window.navigator) {
return true;
} else {
return false;
}
} catch(e) {
return false;
}
}
function isAppceleratorTitanium() {
try {
if (Titanium) {
return true;
} else {
return false;
}
} catch(e) {
return false;
}
}
//A generic extend function - thanks MooTools
function extend(original, extended) {
for (var key in (extended || {})) {
if (original.hasOwnProperty(key)) {
original[key] = extended[key];
}
}
return original;
}
//Check if an object is an array
function isArray(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
//Grab an XMLHTTPRequest Object
function getXHR() {
var xhr;
if (isBrowserEnvironment()) {
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
else if (isAppceleratorTitanium()) {
xhr = Titanium.Network.createHTTPClient();
}
return xhr;
}
//Parse a string and create an XML DOM object
function xmlDomFromString(_xml) {
var xmlDoc = null;
if (isBrowserEnvironment()) {
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(_xml,"text/xml");
}
else {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(_xml);
}
}
else if (isAppceleratorTitanium()) {
xmlDoc = Titanium.XML.parseString(_xml);
}
return xmlDoc;
}
// Convert a JavaScript object to an XML string - takes either an
function convertToXml(_obj, namespacePrefix) {
var xml = '';
if (isArray(_obj)) {
for (var i = 0; i < _obj.length; i++) {
xml += convertToXml(_obj[i], namespacePrefix);
}
} else {
//For now assuming we either have an array or an object graph
for (var key in _obj) {
if (namespacePrefix && namespacePrefix.length) {
xml += '<' + namespacePrefix + ':' + key + '>';
} else {
xml += '<'+key+'>';
}
if (isArray(_obj[key]) || (typeof _obj[key] == 'object' && _obj[key] != null)) {
xml += convertToXml(_obj[key]);
}
else {
xml += _obj[key];
}
if (namespacePrefix && namespacePrefix.length) {
xml += '</' + namespacePrefix + ':' + key + '>';
} else {
xml += '</'+key+'>';
}
}
}
return xml;
}
// Client Configuration
var config = extend({
endpoint:'http://localhost',
targetNamespace: 'http://localhost',
//envelopeBegin: '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:ns0="PLACEHOLDER" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>',
envelopeBegin: '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>',
envelopeEnd: '</soap:Body></soap:Envelope>'
},_options);
// Invoke a web service
this.invoke = function(_soapAction,_body,_callback) {
//Build request body
var body = _body;
//Allow straight string input for XML body - if not, build from object
if (typeof body !== 'string') {
/*body = '<ns0:'+_soapAction+'>';
body += convertToXml(_body, 'ns0');
body += '</ns0:'+_soapAction+'>';*/
body = '<'+_soapAction+' xmlns="http://tempuri.org/">';
body += convertToXml(_body, '');
body += '</'+_soapAction+'>';
}
var ebegin = config.envelopeBegin;
config.envelopeBegin = ebegin.replace('PLACEHOLDER', config.targetNamespace);
//Build Soapaction header - if no trailing slash in namespace, need to splice one in for soap action
var soapAction = '';
if (config.targetNamespace.lastIndexOf('/') != config.targetNamespace.length - 1) {
soapAction = config.targetNamespace+'/'+_soapAction;
}
else {
soapAction = config.targetNamespace+_soapAction;
}
//POST XML document to service endpoint
var xhr = getXHR();
xhr.onload = function() {
//Ti.API.info('Response Text ---->'+this.responseText);
_callback.call(this, xmlDomFromString(this.responseText),xhr.status);
};
xhr.onerror = function() {
//Ti.API.info('Error Response Text ---->'+this.responseText);
_callback.call(this, '',xhr.status);
};
xhr.open('POST',config.endpoint);
xhr.setRequestHeader('Content-Type', 'text/xml');
//Ti.API.info('soapActio---->'+soapAction);
xhr.setRequestHeader('SOAPAction', soapAction);
//Ti.API.info('ReQ---->'+config.envelopeBegin+body+config.envelopeEnd);
xhr.send(config.envelopeBegin+body+config.envelopeEnd);
};
}
Customer remarks
To observe Heap Memory, use Deprecated LogCat from DDMS and filter with the key word "Heap". I have attached screen shot and .apk as well.
Please help us to resolve it soon, as our project is in really critical phase and getting delayed because of "Out Of Memory Exception".
How ever same code works awesome on IOS but this critical issue is only with Android.
Associated thread Community
http://developer.appcelerator.com/question/144219/http-client-sudsjs-fails-to-deallocate-heap-memory
Updated Test Case, reproduction steps and labels. It should be moved to main project to dig into it.
Change the inner classes to static classes so that parent is garbage collected even though inner class instance is referenced (in this case, the ClientRunnable and the thread) https://github.com/appcelerator/titanium_mobile/pull/4862
Looks like the server mentioned in the test case is down.
Hi Sunila, I have uploaded new installer apk and source code in below links. Source Code : https://dl.dropboxusercontent.com/u/65664379/AppceleratorMemoryIssueExample/source/webserviceCall%20copy%202.zip apk: https://dl.dropboxusercontent.com/u/65664379/AppceleratorMemoryIssueExample/installer/app.apk Sorry for the inconvenience. Regards, Mutturaj
https://github.com/appcelerator/titanium_mobile/pull/5670
Testde using the app mentioned by mutturaj. HttpClient successfully deallocate heap memory and app does not crash after reaching certain amount of memory ,also no memory exceptions are generated. Verified the fix on: Device : Google Nexus 5, Android Version: 4.4.2 SDK: 3.3.0.v20140512162513 CLI version : 3.3.0-dev OS : MAC OSX 10.9.2 Alloy: 1.4.0-dev ACS: 1.0.14 npm:1.3.2 LiveView: 1.0.4 Appcelerator Studio, build: 3.3.0.201405121247 titanium-code-processor: 1.1.1 XCode : 5.1.1
The PR that fixed this has a bug, reopening this ticket to fix that bug.
master PR https://github.com/appcelerator/titanium_mobile/pull/5794 3.3.X PR https://github.com/appcelerator/titanium_mobile/pull/5795
Verified the fix. Used the app source code attached by [~mutturajb@gmail.com]. We do not see "Out Of Memory Exceptions" & the app does not crash. Closing. Environment: Appc Studio : 3.3.0.201406111952 Ti SDK : 3.3.0.v20140616174113 Mac OSX : 10.8.5 Alloy : 1.4.0-rc CLI - 3.3.0-rc Code Processor: 1.1.1 sony xperia: 2.3.7 android emulator: 4.0.3