【问题标题】:OutOfMemoryError occurs using YouTube Android player api 1.2.2使用 YouTube Android player api 1.2.2 发生 OutOfMemoryError
【发布时间】:2016-08-23 10:52:21
【问题描述】:

使用 youtube player sdk 播放视频大约 30~40 次会导致 Youtube 应用程序崩溃,然后由于远程进程的死亡,我的应用程序会引发 DeadObjectException。重现步骤:

  1. 启动活动并初始化 YouTubePlayer
  2. 加载并播放视频几秒钟
  3. 释放 YouTubePlayer 并退出活动
  4. 重复步骤 1-3 大约 30~40 次

OutOfMemoryError 日志(full logs):

08-22 12:01:01.461 E/AndroidRuntime( 3017): FATAL EXCEPTION: main
08-22 12:01:01.461 E/AndroidRuntime( 3017): Process: com.google.android.youtube.player, PID: 3017
08-22 12:01:01.461 E/AndroidRuntime( 3017): java.lang.OutOfMemoryError: Could not allocate JNI Env
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.lang.Thread.nativeCreate(Native Method)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.lang.Thread.start(Thread.java:1063)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:921)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ThreadPoolExecutor.ensurePrestart(ThreadPoolExecutor.java:1556)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:310)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:527)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ScheduledThreadPoolExecutor.execute(ScheduledThreadPoolExecutor.java:616)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at reo.a(SourceFile:134)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at sgh.a(SourceFile:722)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at gan.a(SourceFile:310)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at gan.b(SourceFile:338)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at com.google.android.apps.youtube.embeddedplayer.service.service.jar.ApiPlayerService$2.run(SourceFile:215)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.os.Handler.handleCallback(Handler.java:739)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.os.Handler.dispatchMessage(Handler.java:95)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.os.Looper.loop(Looper.java:148)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.app.ActivityThread.main(ActivityThread.java:5417)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.lang.reflect.Method.invoke(Native Method)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

和 DeadObjectException

08-22 12:01:01.842 E/MonitoringInstrumentation( 2976): java.lang.IllegalStateException: android.os.DeadObjectException
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at gix.surfaceCreated(SourceFile:189)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.SurfaceView.updateWindow(SurfaceView.java:582)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:177)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2055)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer.doCallbacks(Choreographer.java:670)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer.doFrame(Choreographer.java:606)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.Handler.handleCallback(Handler.java:739)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.Handler.dispatchMessage(Handler.java:95)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.Looper.loop(Looper.java:148)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.app.ActivityThread.main(ActivityThread.java:5417)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at java.lang.reflect.Method.invoke(Native Method)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976): Caused by: android.os.DeadObjectException
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.BinderProxy.transactNative(Native Method)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.BinderProxy.transact(Binder.java:503)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at com.google.android.apps.youtube.embeddedplayer.service.service.jar.ISurfaceHolderService$Stub$Proxy.a(SourceFile:110)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at gix.surfaceCreated(SourceFile:186)

YouTube 应用版本是 11.29.55 ,带有 Marshmallow 的 Nexus 5 模拟器 ,我用其他版本的YouTube App测试过,比如10.25.57和10.40.58,仍然出现OOM。

刚开始遇到这个问题的时候,我以为只是一些不正确的api方法调用引起的,但是经过几个小时的研究,我发现应该是YouTube App的问题,希望有人能帮助我解决这个问题,或者至少避免它。

在播放器初始化和从内存监视器播放视频时,进程com.google.android.youtube.player 的内存正在增加,并且许多YoutubeService 实例已创建但未从转储文件中回收。有什么想法吗?

我使用基于官方 YouTubeAndroidAPI 示例的演示应用程序对其进行测试,并且也发生 OutOfMemory 错误,我只是将 PlayerViewDemoActivity 中的 loadVideo(String) 替换为 loadVideo(String) 以进行自动播放,并在 @ 中添加了 YouTubePlayer#release() 987654331@,我还添加了一个基于 Espresso 的测试代码来重现内存泄漏问题。

这里是测试代码,here 是完整的演示代码。

package com.examples.youtubeapidemo.play;

import android.os.SystemClock;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;

import com.examples.youtubeapidemo.YouTubeAPIDemoActivity;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.pressBack;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.matcher.ViewMatchers.withText;

/**
 * for YouTubePlayerView testing
 */
@RunWith(AndroidJUnit4.class)
@LargeTest
public class PlayerViewTest {

    @Rule
    public ActivityTestRule<YouTubeAPIDemoActivity> mActivityTestRule =
            new ActivityTestRule<YouTubeAPIDemoActivity>(YouTubeAPIDemoActivity.class);

    @Test
    public void testYouTubeMemoryLeaks() {
        int count = 0;
        while(count < 100) {
            onView(withText("Simple PlayerView")).perform(click());
            SystemClock.sleep(10000); // waiting for video start playing
            pressBack();
            count++;
            Log.i("PlayerViewTest", "count: " + count);
        }
    }
}

【问题讨论】:

  • 您找到解决方法了吗?我现在正尝试在我的应用程序中实现它,它永远不会释放实例,导致巨大的内存泄漏。
  • @Drew 我发现了一个肮脏的解决方法,它有效,但我永远不会鼓励任何人实施它。我注意到com.google.android.youtube 进程可以被activityManager.killBackgroundProcesses("com.google.android.youtube"); 手动杀死,这需要android.permission.KILL_BACKGROUND_PROCESSES 的权限并且必须在youtube 播放器实例发布后执行。
  • 我的实现是每 10 个 YouTube 播放器初始化就杀死进程,它运行良好并通过了我的测试,但我仍然认为手动杀死其他进程绝对是个坏主意。另外我从 crash stats 平台查看了 crash 统计,发现 OOM 崩溃的用户很少,(每周 1~2 次,相对于每天 50k 活跃用户,这可能与我的应用程序的设计有关,只有少数用户有耐心浏览超过 30 多个视频),然后我决定忽略它。

标签: android android-youtube-api


【解决方案1】:

我通过将 youtube 调用(如 youtubePlayer.loadVideo()、cueVideo()、getCurrentTimeMillis() 等)放入 try catch 块并捕获 IllegalStateException 异常,然后重新初始化 youtube 播放器,从而减少了错误的发生。

并通过捕获这些异常并重新启动活动来解决它,

请参阅我在此线程上的回答: Getting a lot of crashes from android youtube player api

【讨论】:

    猜你喜欢
    • 2013-01-03
    • 2015-12-31
    • 2014-02-02
    • 2018-11-14
    • 2015-02-10
    • 2017-10-12
    • 2015-12-23
    • 1970-01-01
    相关资源
    最近更新 更多