I'm writing an Android App which is opening a locally stored html file check.html
. This html file is showing some nice text and then http-forwarding to my real wanted webpage. Now it can happen, that the server is down, or even the network is unplugged, but I want the app to keep trying to reach it all the time.
In case that just the server is down, Android has some latency when asking for the webpage before returning to onReceivedError()
, so I don't have a problem, but if the network is unplugged, it returns immediately.
After 1 to 2 minutes my app crashes with:
08-22 14:17:47.382: D/dalvikvm(8337): GC_CONCURRENT freed 178K, 3% free 12530K/12807K, paused 0ms+7ms
08-22 14:17:57.572: D/dalvikvm(8337): GC_CONCURRENT freed 235K, 3% free 14253K/14599K, paused 0ms+7ms
08-22 14:18:07.882: D/dalvikvm(8337): GC_CONCURRENT freed 241K, 3% free 15969K/16327K, paused 0ms+10ms
08-22 14:18:17.717: D/dalvikvm(8337): GC_CONCURRENT freed 237K, 2% free 17717K/18055K, paused 0ms+13ms
08-22 14:18:28.757: D/dalvikvm(8337): GC_CONCURRENT freed 249K, 2% free 19468K/19783K, paused 3ms+3ms
08-22 14:18:39.105: D/dalvikvm(8337): GC_CONCURRENT freed 241K, 2% free 21185K/21511K, paused 4ms+10ms
08-22 14:18:49.008: D/dalvikvm(8337): GC_CONCURRENT freed 238K, 2% free 22900K/23239K, paused 0ms+10ms
08-22 14:18:51.157: E/dalvikvm(8337): JNI ERROR (app bug): local reference table overflow (max=512)
08-22 14:18:51.157: W/dalvikvm(8337): JNI local reference table (0x1729e78) dump:
08-22 14:18:51.157: W/dalvikvm(8337): Last 10 entries (of 512):
08-22 14:18:51.157: W/dalvikvm(8337): 511: 0x410dec88 android.content.res.AssetManager
08-22 14:18:51.157: W/dalvikvm(8337): 510: 0x4215db30 byte[] (32768 elements)
08-22 14:18:51.157: W/dalvikvm(8337): 509: 0x42155b18 byte[] (32768 elements)
08-22 14:18:51.158: E/dalvikvm(8337): Failed adding to JNI local ref table (has 512 entries)
Here is the code:
mWebView = (WebView) findViewById(R.id.webView);
mWebView.setWebChromeClient(new KB_WebChromeClient(this));
mWebView.setWebViewClient(new KB_WebViewClient());
mWebView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
mWebView.clearCache(true);
mWebView.clearHistory();
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.addJavascriptInterface(new WebAppInterface(this, this), "Android");
mWebView.loadUrl("file:///android_asset/check.html");
The WebViewClient has the following code:
public class KB_WebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.clearCache(true);
}
@Override
public void onReceivedError (WebView view, int errorCode, String description, String failingUrl)
{
view.loadUrl("file:///android_asset/check.html");
}
}
Basically, the check.html
page is loaded, onPageFinished
is called and then the html forwards to the other page, which is not working, so onReceivedError
is called, which will start loading the check.html
again aso.
On my research I found SO: Android Expand JNI Local Reference Table, where the answer is
You need to delete local references to classes as well as to objects.
What does it mean and where is my problem? Does webview.loadUrl create anything complex and the Garbage Collector is not fast enough to clean up? I don't create the WebView all the time, so what is messing around?
Thanks for help in advance!
edit: I implemented a counter which counts how often the webview.loadUrl is called. It counts 280 to 290 before the app crashes. I tried to remove the check.html
and just load my wanted webpage in the network, then the amount of tries goes up to 570 before crashing. It seams, that every webpage load is counted, even when it's done from the HTML page. I was having a look at the heap of the system and what I saw is that every time when one loop is done, there are 1 to 3 more byte[] arrays with 32kB size allocated and not freed. Even the Garbage Collection doesn't free it. I will try to get rid of the Webview every x tries. Maybe that workaround could work...
edit: Under the link they show that there is a bug:
It seems that there is a leakage in the external/webkit/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp.
if (!m_buffer) {
m_buffer = env->NewByteArray(out->capacity());
m_buffer = (jbyteArray) env->NewGlobalRef(m_buffer);
}
A local reference is created by NewByteArray but it's not deleted.
I think that this could be related to my problem. I'm running Android 4.0.3 and I can't update, as it seems they fixed that problem....well well, I'll try to find a workaround.