2013-08-22 118 views
0

我正在写一个Android应用程序,它打开本地存储的HTML文件check.html。这个html文件显示了一些不错的文本,然后http转发到我真正想要的网页。现在可能会发生,服务器关闭,甚至网络拔掉,但我希望应用程序一直试图达到它。Android Webview JNI错误与loadUrl

如果只是服务器停机,Android在返回onReceivedError()之前询问网页时会有一些延迟,所以我没有问题,但是如果拔掉网络,它会立即返回。

后用1〜2分钟我的应用程序崩溃:

08-22 14:17:47.382:d/dalvikvm(8337):GC_CONCURRENT释放178K,3%的游离12530K/12807K,暂停0毫秒+ 7毫秒
08-22 14:17:57.572:d/dalvikvm(8337):GC_CONCURRENT释放235K,3%的游离14253K/14599K,暂停0毫秒+ 7毫秒
08-22 14:18:07.882:d/dalvikvm(8337 ):GC_CONCURRENT已释放241K,3%空闲15969K/16327K,暂停0ms + 10ms
08-22 14:18:17.717:D/dalvikvm(8337):GC_CONCURRENT已释放237K,2%空闲17717K/18055K,暂停0ms + 13ms
08-22 14:18:28.757:D/d alvikvm(8337):GC_CONCURRENT已释放249K,2%免费19468K/19783K,暂停3ms + 3ms
08-22 14:18:39.105:D/dalvikvm(8337):GC_CONCURRENT已释放241K,2%免费21185K/21511K,暂停4ms + 10ms
08-22 14:18:49.008:D/dalvikvm(8337):GC_CONCURRENT已释放238K,2%空闲22900K/23239K,暂停0ms + 10ms
08-22 14:18:51.157:E/dalvikvm (8337):JNI ERROR(app bug):本地参考表溢出(max = 512)
08-22 14:18:51.157:W/dalvikvm(8337):JNI本地参考表(0x1729e78)dump:
08 -22 14:18:51.157:W/dalvikvm(8337):最后10项(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种元素)
08-22 14:18:51.158:E/dalvikvm(8337):无法增加JNI本地参考表(已512个条目)

下面是代码:

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"); 

WebViewClient具有以下代码:

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"); 
    } 
} 

基本上,check.html页面被加载,onPageFinished被调用,然后html转发到另一个页面,这是不工作,所以onReceivedError被调用,这将开始加载check.html aso。

我的研究,我发现SO: Android Expand JNI Local Reference Table,这里的答案是

您需要删除本地引用到类和对象。

这是什么意思,我的问题在哪里? webview.loadUrl是否创建了任何复杂的内容,垃圾收集器速度不够快,无法清理?我不会一直创建WebView,那么在搞什么?

感谢您的帮助!

编辑:我实现了一个计数器来计算调用webview.loadUrl的频率。它在应用程序崩溃之前计算280到290。我试图删除check.html,并在网络中加载我想要的网页,然后在崩溃之前尝试的数量上升到570。它接近每个网页负载,即使从HTML页面完成。我查看了系统的堆,我看到的是每当完成一个循环时,还有1到3个字节数组分配了32kB大小并且没有被释放。即使垃圾收集也没有释放它。我会尽力摆脱Web视图每x次尝试。也许这可以解决方法工作...

编辑:下,它们表明,有一个错误的link

似乎有外部/ WebKit的/来源/ WebKit的漏/安卓/ WebCoreSupport/UrlInterceptResponse.cpp。
if(!m_buffer){
m_buffer = env-> NewByteArray(out-> capacity());
m_buffer =(jbyteArray)env-> NewGlobalRef(m_buffer);
}

本地引用由NewByteArray创建,但不会被删除。

我认为这可能与我的问题有关。我正在运行Android 4.0.3,我无法更新,因为它似乎解决了这个问题....好吧,我会尽力找到解决方法。

回答

1

据我了解,Android的WebView在加载页面时存在内存泄漏(请参阅链接问题编辑)。有人可能会想到,解决方法是销毁WebView。它可以工作,但由于某些原因,WebView无法销毁(至少GC无法清理),因为它与活动相关联。 解决方法是在多次尝试后销毁活动。我决定每150次尝试一次。

WebViewClient:

@Override 
public void onReceivedError (WebView view, int errorCode, String description, String failingUrl) 
{ 
    counter++; 
    if(150 == counter){ 
     mainActivity.KillThisThenStartNewOne(); 
    } 
    view.loadUrl("file:///android_asset/check.html"); 
} 

活动:

public void KillThisThenStartNewOne(){ 
    Intent intent = new Intent(this.getApplicationContext(), MainActivity.class); 
    intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     this.getApplicationContext().startActivity(intent); 
     //for restarting the Activity 
     android.os.Process.killProcess(android.os.Process.myPid()); 
     System.exit(0); 
} 

测试在Android 4.0.3和作品。活动的重新启动大约需要0.5到1秒。

+0

我与你有同样的问题。但我不知道如何解决这个问题。我只是使用WebView来加载几个(很多)html文件。不是NDK,不是jni。如何解决这个错误?你能给我一些帮助吗? –

+0

在我的应用程序中,我只是加载本地html文件。不是来自互联网。我也有同样的问题。对于我的情况,onReceivedError永远不会被调用。我不知道你的解决方法是不错的选择。 –

+0

我该如何解决这个问题?我的webview需要加载太多的本地html文件。 –

0
public void onReceivedError (WebView view, int errorCode, String description, String failingUrl) 
    { 
     view.loadUrl("file:///android_asset/check.html"); 
    } 

你这样做很快我想,在一种循环。创建一个处理程序并将其发布到(一个)处理程序上可能会解决此问题。喜欢的东西:

private Handler handler = new Handler(); 

@Override 
public void onReceivedError (final WebView view, int errorCode, String description, String failingUrl) { 

    handler.postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      if (view != null && view.isActivated()) { 
        view.loadUrl("file:///android_asset/check.html"); 
      } 
     } 
    }, 500); 
} 

我认为你做了10000页的URL负载在这些1-2分钟,现在你会做每0.5秒一张支票,你的应用程序会喜欢好多了,不会再崩溃。

+0

所以你会说,我的问题是尝试的速度(就像没有网络连接时的每次尝试都是500毫秒),系统太慢,无法照顾我的垃圾?我可以等待10秒没有问题,但我的恐惧是,我的问题只是推迟了4小时的工作与下面的崩溃工作... – Micky

+0

是的,尝试的速度。放一个日志语句并检查:如果你在几秒钟内进入100次onReceivedError方法,那么肯定会出现问题。随着你的循环,你可能会堵塞整个系统。 – Frank

+0

我把一个计数器记录下来,并显示给我。就像我说的,每次尝试都需要大约500毫秒,经过280次计数后崩溃。所以我敢打赌,即使我等了10秒钟,我会在280 + - x次尝试后得到问题。 – Micky