jjzjj

android - com.google.android.gms.internal.* 引起的内存泄漏

coder 2023-12-05 原文

我正在使用 smart-location-lib 一次获取设备的当前位置。它需要在 Activity 的生命周期中稍后使用。

从 Activity 执行 finish() 以返回到上一个 Activity 时,出现内存泄漏。

代码如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...

    SmartLocation.with(this).location()
    .oneFix()
    .start(new OnLocationUpdatedListener() {
        @Override
        public void onLocationUpdated(Location location) {
            mCurrentLocation = location;
        }
    });

    ...
}

...

@Override
protected void onStop() {
    super.onStop();

    SmartLocation.with(this).location().stop();
}

如您所见,我在 Activity 的 onStop() 调用中执行 smart-location-lib 的 .stop(),如文档 here 中所述。

但这并不能防止泄漏。以下是使用 LeakCanary 收集的有关泄漏的信息:

In com.companyname.appname.development:1.0-development:1.
* com.companyname.appname.activities.TaskCheckoutActivity has leaked:
* GC ROOT com.google.android.gms.internal.zzbyw.zzfwc
* references com.google.android.gms.internal.zzbyt.zzhyy
* references io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider.context
* leaks com.companyname.appname.activities.TaskCheckoutActivity instance

* Retaining: 1,6 MB.
* Reference Key: ba2a19b1-d5ca-4971-a5c7-e0fd99ea95a6
* Device: samsung samsung SM-G930F heroltexx
* Android Version: 7.0 API: 24 LeakCanary: 1.5.4 74837f0
* Durations: watch=5010ms, gc=215ms, heap dump=1792ms, analysis=128865ms

* Details:
* Instance of com.google.android.gms.internal.zzbyw
|   static $classOverhead = byte[752]@858164225 (0x33268c01)
|   zzfwc = com.google.android.gms.internal.zzbyt@861919192 (0x335fd7d8)
|   mDescriptor = java.lang.String@854648480 (0x32f0e6a0)
|   mObject = 501026202704
|   mOwner = com.google.android.gms.internal.zzbyw@856066112 (0x33068840)
|   shadow$_klass_ = com.google.android.gms.internal.zzbyw
|   shadow$_monitor_ = 0
* Instance of com.google.android.gms.internal.zzbyt
|   static $classOverhead = byte[792]@855184385 (0x32f91401)
|   zzhyy = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider@856875576 (0x3312e238)
|   zzfda = com.google.android.gms.common.api.Api@856792448 (0x33119d80)
|   zzfip = com.google.android.gms.common.api.Api$zzf@854593816 (0x32f01118)
|   mStatus = com.google.android.gms.common.api.Status@856929688 (0x3313b598)
|   zzaj = true
|   zzaop = java.util.concurrent.CountDownLatch@855708832 (0x330114a0)
|   zzfhl = com.google.android.gms.common.api.Status@856929688 (0x3313b598)
|   zzfiz = java.lang.Object@854593632 (0x32f01060)
|   zzfja = com.google.android.gms.common.api.internal.zzu@856066144 (0x33068860)
|   zzfjb = java.lang.ref.WeakReference@857866976 (0x332202e0)
|   zzfjc = java.util.ArrayList@857867120 (0x33220370)
|   zzfjd = null
|   zzfje = java.util.concurrent.atomic.AtomicReference@855708848 (0x330114b0)
|   zzfjf = null
|   zzfjg = false
|   zzfjh = false
|   zzfji = null
|   zzfjj = null
|   zzfjk = false
|   shadow$_klass_ = com.google.android.gms.internal.zzbyt
|   shadow$_monitor_ = -1953408656
* Instance of io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider
|   static REQUEST_CHECK_SETTINGS = 20001
|   static GMS_ID = java.lang.String@856784656 (0x33117f10)
|   static $classOverhead = byte[748]@857097217 (0x33164401)
|   static REQUEST_START_LOCATION_FIX = 10001
|   alwaysShow = true
|   checkLocationSettings = false
|   client = com.google.android.gms.common.api.internal.zzbd@856996208 (0x3314b970)
|   context = com.companyname.appname.activities.TaskCheckoutActivity@860313600 (0x33475800)
|   fulfilledCheckLocationSettings = false
|   googlePlayServicesListener = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesWithFallbackProvider@856791392 (0x33119960)
|   listener = com.companyname.appname.activities.TaskCheckoutActivity$1@856799680 (0x3311b9c0)
|   locationRequest = com.google.android.gms.location.LocationRequest@856876304 (0x3312e510)
|   locationStore = io.nlopez.smartlocation.location.LocationStore@859517520 (0x333b3250)
|   logger = io.nlopez.smartlocation.utils.LoggerFactory$Sssht@854569160 (0x32efb0c8)
|   serviceListener = null
|   settingsResultCallback = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider$1@856798672 (0x3311b5d0)
|   shouldStart = false
|   stopped = true
|   shadow$_klass_ = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider
|   shadow$_monitor_ = -2147272239
* Instance of com.companyname.appname.activities.TaskCheckoutActivity
|   static $classOverhead = byte[4720]@856289281 (0x3309f001)
|   BARCODE_SCANNER_REQUEST = java.lang.Integer@856384016 (0x330b6210)
|   BEGIN_SIGNATURE_REQUEST = java.lang.Integer@856384000 (0x330b6200)
|   mApiKey = java.lang.String@856965696 (0x33144240)
|   mCheckoutEmptyStepView = null
|   mCurrentLocation = android.location.Location@859607248 (0x333c90d0)
|   mDamagedAddressUnknownDescriptionCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mDamagedAddressUnknownDescriptionEditText = null
|   mDamagedAddressUnknownStepView = null
|   mJobManager = com.birbit.android.jobqueue.JobManager@851730080 (0x32c45ea0)
|   mKibCardInputCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mKibCardInputEditText = null
|   mKibCardInputStepView = null
|   mKibCardNextTimeframe = null
|   mKibNextAbbrevation = null
|   mKibNextDay = null
|   mMarginBetweenStatusAndIcons = android.support.v7.widget.AppCompatTextView@860264448 (0x33469800)
|   mNameCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourAddressStepView = null
|   mNeighbourCityFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourCityInputEditText = null
|   mNeighbourStreetFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourStreetInputEditText = null
|   mNeighbourStreetNumberFailed = java.lang.Boolean@1881937152 (0x702c1500)
|   mNeighbourStreetNumberInputEditText = null
|   mNeighbourZipcodeFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourZipcodeInputEditText = null
|   mOpenBarcodeScannerButton = null
|   mParcelKey = java.lang.String@856985856 (0x33149100)
|   mPaymentCompleted = java.lang.Boolean@1881937168 (0x702c1510)
|   mPaymentStepView = null
|   mPaymentSwitch = null
|   mPaymentTextView = null
|   mRecipientContainer = android.widget.RelativeLayout@860361728 (0x33481400)
|   mRecipientNameEditText = android.widget.EditText@860366848 (0x33482800)
|   mRefusedReasonCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mRefusedReasonEditText = null
|   mRefusedStepView = null
|   mSignatureBitmap = android.graphics.Bitmap@854106464 (0x32e8a160)
|   mSignatureButton = android.widget.Button@860369920 (0x33483400)
|   mSignatureFragmentContainer = android.widget.RelativeLayout@860368896 (0x33483000)
|   mSignaturePreviewImageView = android.widget.ImageView@860370944 (0x33483800)
|   mSignatureStepView = android.widget.RelativeLayout@860360704 (0x33481000)
|   mSigned = java.lang.Boolean@1881937152 (0x702c1500)
|   mSpecialContainerTaskStatusTextView = android.support.v7.widget.AppCompatTextView@860262400 (0x33469000)
|   mSpecialIconA = android.support.v7.widget.AppCompatImageView@860296192 (0x33471400)
|   mSpecialIconB = android.support.v7.widget.AppCompatImageView@860297216 (0x33471800)
|   mSpecialIconC = android.support.v7.widget.AppCompatImageView@860298240 (0x33471c00)
|   mSpecialIconD = android.support.v7.widget.AppCompatImageView@860299264 (0x33472000)
|   mSpecialIconsLinearLayout = android.widget.LinearLayout@860261376 (0x33468c00)
|   mSteps = java.lang.String[2]@860283592 (0x3346e2c8)
|   mTask = com.companyname.appname.models..Task@857797632 (0x3320f400)
|   mTaskCheckout = com.companyname.appname.helpers.TaskCheckout@859397192 (0x33395c48)
|   mTaskCheckoutMainLinLayout = android.widget.LinearLayout@856667136 (0x330fb400)
|   mTaskStatus = com.companyname.appname.enums.TaskStatus@851451392 (0x32c01e00)
|   mTaskStatusLabel = android.widget.TextView@860358656 (0x33480800)
|   mTaskStatusSelectedIndex = java.lang.Integer@1882345520 (0x70325030)
|   mTaskStatusText = java.lang.String@858039008 (0x3324a2e0)
|   mTaskStatusTextView = android.widget.TextView@860359680 (0x33480c00)
|   mTaskStatusView = android.widget.FrameLayout@860321792 (0x33477800)
|   mVerticalStepperForm = ernestoyaquello.com.verticalstepperform.VerticalStepperFormLayout@860300288 (0x33472400)
|   mDelegate = android.support.v7.app.AppCompatDelegateImplN@856322976 (0x330a73a0)
|   mResources = null
|   mThemeId = 2131427510
|   mCreated = true
|   mFragments = android.support.v4.app.FragmentController@856383984 (0x330b61f0)
|   mHandler = android.support.v4.app.FragmentActivity$1@856395936 (0x330b90a0)
|   mNextCandidateRequestIndex = 0
|   mPendingFragmentActivityResults = android.support.v4.util.SparseArrayCompat@856400656 (0x330ba310)
|   mReallyStopped = true
|   mRequestedPermissionsFromFragment = false
|   mResumed = false
|   mRetaining = false
|   mStopped = true
|   mStartedActivityFromFragment = false
|   mStartedIntentSenderFromFragment = false
|   mExtraDataMap = android.support.v4.util.SimpleArrayMap@856309016 (0x330a3d18)
|   mActionBar = null
|   mActionModeTypeStarting = 0
|   mActivityInfo = android.content.pm.ActivityInfo@855609200 (0x32ff8f70)
|   mActivityTransitionState = android.app.ActivityTransitionState@856227168 (0x3308fd60)
|   mAppLockCheckRunnable = android.app.Activity$1@856383936 (0x330b61c0)
|   mAppLockIsInMultiWindowMode = false
|   mApplication = com.companyname.appname.DeliveryApplication@851900944 (0x32c6fa10)
|   mCalled = true
|   mChangeCanvasToTranslucent = false
|   mChangingConfigurations = false
|   mComponent = android.content.ComponentName@856313936 (0x330a5050)
|   mConfigChangeFlags = 0
|   mCurrentConfig = android.content.res.Configuration@855650184 (0x33002f88)
|   mDecor = null
|   mDefaultKeyMode = 0
|   mDefaultKeySsb = null
|   mDestroyed = true
|   mDoReportFullyDrawn = false
|   mEatKeyUpEvent = false
|   mEmbeddedID = null
|   mEnableDefaultActionBarUp = false
|   mEnterTransitionListener = android.app.SharedElementCallback$1@1891321968 (0x70bb4870)
|   mExitTransitionListener = android.app.SharedElementCallback$1@1891321968 (0x70bb4870)
|   mFinished = true
|   mFlipfont = 0
|   mFragments = android.app.FragmentController@856383904 (0x330b61a0)
|   mHandler = android.os.Handler@856395872 (0x330b9060)
|   mHasCurrentPermissionsRequest = false
|   mIdent = 226856808
|   mInstanceTracker = android.os.StrictMode$InstanceTracker@856383920 (0x330b61b0)
|   mInstrumentation = android.app.Instrumentation@851709880 (0x32c40fb8)
|   mIntent = android.content.Intent@858578880 (0x332cdfc0)
|   mLastNonConfigurationInstances = null
|   mMainThread = android.app.ActivityThread@851460448 (0x32c04160)
|   mManagedCursors = java.util.ArrayList@856308968 (0x330a3ce8)
|   mManagedDialogs = null
|   mMenuInflater = null
|   mParent = null
|   mPolicyManager = null
|   mReferrer = java.lang.String@856356128 (0x330af520)
|   mResultCode = -1
|   mResultData = null
|   mResumed = false
|   mScreenChangeListener = null
|   mSearchEvent = null
|   mSearchManager = null
|   mStartedActivity = false
|   mStopped = true
|   mTaskDescription = android.app.ActivityManager$TaskDescription@856395904 (0x330b9080)
|   mTemporaryPause = false
|   mTitle = java.lang.String@851901504 (0x32c6fc40)
|   mTitleColor = 0
|   mTitleReady = true
|   mToken = android.os.BinderProxy@856318080 (0x330a6080)
|   mTranslucentCallback = null
|   mUiThread = java.lang.Thread@1999246640 (0x772a1530)
|   mVisibleBehind = false
|   mVisibleFromClient = true
|   mVisibleFromServer = true
|   mVoiceInteractor = null
|   mWindow = com.android.internal.policy.PhoneWindow@860593808 (0x334b9e90)
|   mWindowAdded = true
|   mWindowManager = android.view.WindowManagerImpl@856400152 (0x330ba118)
|   mInflater = com.android.internal.policy.PhoneLayoutInflater@858279648 (0x33284ee0)
|   mOverrideConfiguration = null
|   mResources = android.content.res.Resources@858466752 (0x332b29c0)
|   mTheme = android.content.res.Resources$Theme@856384208 (0x330b62d0)
|   mThemeResource = 2131427510
|   mBase = android.app.ContextImpl@854679440 (0x32f15f90)
|   shadow$_klass_ = com.companyname.appname.activities.TaskCheckoutActivity
|   shadow$_monitor_ = 1073743558
* Excluded Refs:
| Field: android.view.inputmethod.InputMethodManager.mNextServedView
| Field: android.view.inputmethod.InputMethodManager.mServedView
| Field: android.view.inputmethod.InputMethodManager.mServedInputConnection
| Field: android.view.textservice.SpellCheckerSession$1.this$0
| Field: com.samsung.android.content.clipboard.SemClipboardManager.mContext
| Field: com.samsung.android.emergencymode.SemEmergencyManager.mContext
| Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always)
| Thread:FinalizerWatchdogDaemon (always)
| Thread:main (always)
| Thread:LeakCanary-Heap-Dump (always)
| Class:java.lang.ref.WeakReference (always)
| Class:java.lang.ref.SoftReference (always)
| Class:java.lang.ref.PhantomReference (always)
| Class:java.lang.ref.Finalizer (always)
| Class:java.lang.ref.FinalizerReference (always)

我试过不使用 smart-location-lib 并实现代码来获取当前位置,如 Android here 的官方培训文档中所写。但这也会导致 com.google.android.gms.internal.* 发生内存泄漏。

我已经在两台设备(Android 7.0 上的 Galaxy S7 和 Android 5.1.1 上的 Galaxy J2 2016)上试过了,它们都会产生内存泄漏。该项目使用compile 'com.google.android.gms:play-services-location:11.2.2'

我做错了什么?

最佳答案

我在做动画时遇到了与 android.widget 对象(如 imageview、按钮等)相同的问题,所以我创建了静态内部类,如下所示,而不是匿名或非静态内部类,并且在静态中我存储了 android.widget 对象在弱引用中。

private static class ImageViewAnimation implements ValueAnimator.AnimatorUpdateListener {

    private final WeakReference<ImageView> mpetImageView;
    private int axis;

    public ImageViewAnimation(ImageView mpetImageView, int axis) {
        this.mpetImageView = new WeakReference<>(mpetImageView);
        this.axis = axis;
    }

    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        ImageView view = mpetImageView.get();
        int value = (int) valueAnimator.getAnimatedValue();
        if (this.axis == 1) {
            view.setTranslationX(value);
        } else if (this.axis == 2) {
            view.setTranslationY(value);
        }
    }
}

我在我的 Activity 中使用上面的类作为 petx.addUpdateListener(new ImageViewAnimation(petImageView, 1));

您的用例从这个示例中获取的信息如下

  • 尝试创建一个静态内部类并使其实现 OnLocationUpdatedListener 并在您需要的任何地方使用该类实例。
  • 确保您使用的 android.Location 实例 mcurretLocation 是非静态的
  • 尝试在 onPause()onDestroy() 中显式使 android.Location 实例为空

关于android - com.google.android.gms.internal.* 引起的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46391856/

有关android - com.google.android.gms.internal.* 引起的内存泄漏的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  3. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  4. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  5. ruby-on-rails - HTTParty 的内存问题和下载大文件 - 2

    这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e

  6. ruby - Google-api-ruby-client 翻译 API 示例 - 2

    很高兴看到google代码:google-api-ruby-client项目,因为这对我来说意味着Ruby人员可以使用GoogleAPI-s来完善代码。虽然我现在很困惑,因为给出的唯一示例使用Buzz,并且根据我的实验,Google翻译(v2)api的行为必须与google-api-ruby-client中的Buzz完全不同。.我对“Explorer”演示示例很感兴趣——但据我所知,它并不是一个探索器。它所做的只是调用一个Buzz服务,然后浏览它已经知道的关于Buzz服务的事情。对我来说,Explorer应该让您“发现”所公开的服务和方法/功能,而不一定已经知道它们。我很想听听使用这个

  7. ruby - 如何从 URL 中删除 Google 跟踪参数 (UTM)? - 2

    我有一堆要清理的URL。它们都包含UTM参数,在这种情况下不是必需的,或者是有害的。示例:http://houseofbuttons.tumblr.com/post/22326009438?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+HouseOfButtons+%28House+of+Buttons%29所有可能的参数都以utm_开头。如何使用ruby​​脚本/结构轻松删除它们而不破坏其他潜在的“好”URL参数? 最佳答案 您可以将正则表达式应用于url以清

  8. ruby - 警告 : PATH set to RVM ruby but GEM_HOME and/or GEM_PATH not set, 请参阅 : https://github. com/wayneeseguin/rvm/issues/3212 - 2

    我每次打开终端时都会收到这个错误:警告:PATH设置为RVMruby​​但未设置GEM_HOME和/或GEM_PATH,请参阅:https://github.com/wayneeseguin/rvm/issues/3212这是在我最近安装zsh(oh-my-zsh)后开始发生的我不知道如何设置GEM_HOME和/或GEM_PATH的路径。 最佳答案 我也面临同样的问题,更改.zshrc中的以下行,exportPATH="/usr/local/heroku/bin:.........."到exportPATH="$PATH:/usr/

  9. ruby - 导轨 3 : Creating app with internal plugin system - 2

    我想在Rails中使用插件系统创建一个应用程序。潜在用户应该能够上传(或更好地从存储库安装)一个插件并安装它,使我的应用程序能够做更多的事情。这应该在没有FTP/SSH/对服务器的任何低级别访问的情况下完成。关于如何在Rails3中完成它,是否有任何好的gems或教程? 最佳答案 你看过http://edgeguides.rubyonrails.org/plugins.html了吗??它似乎不是100%兼容Rails3,但它可以帮助您入门。我看过的大多数插件文章都涉及Rails2。 关于

  10. ruby - 尝试授权服务器到 ruby​​ 中的服务器类型应用程序以访问 Google 日历时无效授权 - 2

    我正在尝试为自己创建一个直接连接到我的日历的应用程序……但我从不想参与重新验证。我只想编写一次身份验证代码并完成它。授权码如下:key=Google::APIClient::PKCS12.load_key(SERVICE_ACCOUNT_PKCS12_FILE_PATH,PASSWORD)asserter=Google::APIClient::JWTAsserter.new(SERVICE_ACCOUNT_EMAIL,'https://www.googleapis.com/auth/calendar',key)@client=Google::APIClient.new@client.a

随机推荐