- 博客(120)
- 资源 (3)
- 收藏
- 关注
原创 从KOOM看native内存泄漏监控
不同于Java,在Native层主要使用C或者C++来进行编码,语言本身并没有垃圾回收机制,对于对象的回收依赖于开发者手动释放空间,这也就意味着在native层进行泄漏检测相对而言更加困难,那么Native层内存泄漏就没办法监控了吗?当然有的,在Android N(7.0)以后系统新增了libmemunreachable模块,该模块是一个零开销的本地内存泄漏检测器,其使用不精确的标记-清楚垃圾回收器遍历所有Native内存,并将不可访问的内存块报告为泄漏内存区域。
2023-09-17 20:34:51
290
原创 从Matrix-ResourceCanary看内存快照生成-ForkAnalyseProcessor(1)
前文看到AutoDumpProcessor的处理逻辑主要是生成,裁剪hprof文件并回调到PluginListener中,接下来我们来看下ForkAnalyseProcessor的处理逻辑。
2023-09-07 22:17:33
257
原创 从KOOM看Java内存泄漏检测
前面我们了解了LeakCanary和Matrix Resource Canary中内存泄漏的监控和解析,不难看出LeakCanary是只能在线下部署的,主要原因是因为Debug.dumpHprofData执行会冻结整个应用进程,造成应用进程几秒乃至十多秒不能响应的情况,而dump时机有可能比较频繁,所以不能线上部署。
2023-09-07 22:14:07
324
原创 从Matrix-ResourceCanary看内存快照生成-ForkAnalyseProcessor(2)
不同于LeakCanary,在Matrix中,主要是通过Resource Canary来监控内存泄漏问题的,且监听的泄漏对象只支持Activity,官方说明如下:结合分析LeakCanary的经验可知,要实现Activity内存泄漏监听,总体上应该要实现两大功能:从Activity生命周期监控实现方案可知,我们可以通过Application.registerActivityLifecycleCallbacks来实现Activity生命周期监控,那么Matrix中又是怎么实现的呢?在Matrix中Resour
2023-09-03 15:31:53
225
原创 从LeakCanary看内存快照解析
在从LeakCanary看内存快照生成一节中,我们已经了解了hprof的生成,并且将生成的hprof文件通过Android Studio进行解析,确实发现了内存泄漏对象MainActivity,但是在实际开发中,要求开发者自己去手动pull hprof文件进行解析,相对而言,操作是比较麻烦的,我们期望能通过代码分析出内存泄漏对象的引用链以提示开发者。在LeakCanary早起是通过库进行hprof文件解析的,随后在LeakCanary2.0之后迁移到。
2023-08-30 22:46:28
310
原创 从LeakCanary看内存快照生成
前面我们已经完成了生命周期监控并且可以通过ReferenceQueue和WeakHashMap的比较确定哪些对象发生泄漏了,那么接下来需要考虑的就是如何确定这个对象是被谁持有导致泄漏的呢?从一文中可知,当我们使用Android Studio或MAT分析内存泄漏问题时,通常首先是需要抓取发生内存泄漏时的hprof文件,随后使用分析软件打开该文件,排查泄漏对象被持有的GC Roots,进而解决内存泄漏问题。
2023-08-25 09:45:00
223
原创 从LeakCanary看如何判断对象被回收了
前面已经了解了Service,Fragment,ViewModel对象的销毁时机,那么在触发销毁时机后,我们怎么判断这些对象有没有回收呢?大家都知道在Java中有强引用,弱引用,软引用,虚引用四种引用方式,而我们判断对象是否回收,就需要通过弱引用来实现,针对弱引用而言。
2023-08-20 14:56:38
103
原创 从LeakCanary看ViewModel生命周期监控
在ViewModel机制中,主要包含ViewModelStore,ViewModelStoreOwner和ViewModelProvider这两个角色,其中ViewModelStoreOwner接口由持有ViewModelStore的类实现,ViewModelStore主要用于存储ViewModel对象,ViewModelProvider是一个工具类,用于构造ViewModel对象,同时在构造时会将构造的对象添加到ViewModelStore中。
2023-08-18 23:52:47
230
原创 从LeakCanary看Fragment生命周期监控
前文中我们已经了解到LeakCanary中Service生命销毁的监听方式,那么Fragment的生命周期监听又是怎么实现的呢?Activity生命周期监听,在Application里面有ActivityLifecycleCallbacks,那么Fragment是否相似呢?
2023-08-14 09:45:00
194
原创 从LeakCanary看Service生命周期监控
大家都知道使用LeakCanary可以监控项目中存在的问题,那么LeakCanary是怎么实现的呢?LeakCanary通过检测程序中对象的引用关系,收集应该被回收的对象并标记,随后等待GC后,检查该对象是否按预期回收即可,目前LeakCanary支持Service,Activity,Fragment,ViewModel以及View的泄漏检测,接下来我们一起来看下Service的关联部分。首先,我们考虑如果要认定一个Service对象可以被回收,前提条件是什么?
2023-08-09 21:01:13
159
原创 什么?按Home键SingleInstance Activity销毁了???
前段时间,突然有朋友询问,自己写的SingleInstance Activity在按home键的时候被销毁了,刚听到这个问题的时候,我直觉怀疑是Activity在onPause或者onStop中发生了Crash导致闪退了,但是安装apk查看现象,没有发现异常日志,这究竟是怎么回事呢?编写测试Demo来详细探索下。
2023-07-25 10:00:00
384
原创 ReentrantLock实现原理-条件锁
在前两篇文章中,我们了解了ReentrantLock内部公平锁和非公平锁的实现原理,可以知道其底层基于AQS,使用双向链表实现,同时在线程间通信方式(2)中我们了解到ReentrantLock也是支持条件锁的,接下来我们来看下,其内部条件锁的实现原理。
2023-06-13 10:00:00
283
原创 ReentrantLock实现原理-公平锁
在ReentrantLock实现原理(1)一节中,我们了解了ReentrantLock非公平锁的获取流程,在本节中我们来看下ReentrantLock公平锁的创建以及锁管理流程。
2023-06-12 21:56:49
613
原创 ReentrantLock实现原理-非公平锁
在线程间通信方式2一节中,我们了解了Lock,Condition和ReentrantLock,学习了简单使用Condition和RentrantLock完成线程间通信,从文章中我们了解到ReentrantLock是Lock接口的一个最常用的实现类,ReentrantLock是独占锁,独占锁的场景下又支持公平锁和非公平锁,那么在源码实现中,ReentrantLock继承关系,实现结构又是怎样的呢?
2023-05-04 22:14:37
516
1
原创 Java-volatile实现详解(从java到汇编)
在Java内存模型一节,除了synchronized外,我们还提到一个常用关键词----volatile,我们说过volatile保证了并发环境的可见性和顺序性,使用volatile修饰的变量,当然值发生改变时,可以同步到其他线程,其他线程按新值进行计算,下面我们编写代码来看下volatile关键词的使用和实现原理,验证我们前面抛出的结论。当我们使用多线程对共享变量进行操作时,如果不用volatile,会是什么现象呢?
2023-04-29 14:36:16
912
原创 Java-synchronized实现详解(从Java到汇编)
synchronized作为java语言中的并发关键词,其在代码中出现的频率相当高频,大多数开发者在涉及到并发场景时,一般都会下意识得选取synchronized。
2023-04-28 08:45:00
870
原创 Java多线程与锁
前文中,我们已经了解了什么是线程,线程间常用通信方式,线程池以及其相关特性,可以看出锁在多线程环境中充当着重要作用,不管是线程间的数据通信,还是线程间的等待和唤醒,都依赖于锁,那么锁又有哪些特征以及分类呢?下面我们一起详细看下。
2023-04-27 08:45:00
814
原创 Java线程池工具类-Executors详解
前文介绍到我们可以通过创建ThreadPoolExecutor对象来定制属于自己的线程池,在创建一个线程池时需要关注核心线程数,最大线程数,拒绝策略,线程构造工厂,任何队列等7个参数,相对而言,灵活度偏高,初次使用的开发者在参数设计和处理时,可能会有困惑,所以java.util.oncurrent并发工具包中也为我们提供了快捷创建线程池的工具类,用于创建常见模版线程,这个类叫做Executors。
2023-04-26 22:00:00
613
原创 Java线程池及拒绝策略详解
前文提到线程的使用以及线程间通信方式,通常情况下我们通过new Thread或者new Runnable创建线程,这种情况下,需要开发者手动管理线程的创建和回收,线程对象没有复用,大量的线程对象创建与销毁会引起频繁GC,那么事否有机制自动进行线程的创建,管理和回收呢?线程池可以实现该能力。
2023-04-25 22:02:29
1022
原创 Java线程间通信方式(3)
Semaphore(信号量)PhaserExchanger通信方式应用场景是否可重用子任务异常处理备注大多数线程通信场景是依赖开发者维护,在finally块中完成释放,避免死锁Semaphore(信号量)通知唤醒类线程间通信场景是依赖开发者维护,在finally块中释放信号量,避免死锁串行多线程运行场景否不加处理的话,子任务发生异常导致退出,则所有等待的线程都会一致等待,直到超时时间来临聚合类线程通信场景否。
2023-04-25 21:39:25
990
原创 Java线程间通信方式(2)
前文了解了线程通信方式中的Object.wait/Object.notify以及Semaphore,接下来我们继续了解其他的线程间通信方式。
2023-04-25 21:33:11
374
原创 Java线程间通信方式
前文了解了线程的创建方式和状态切换,在实际开发时,一个进程中往往有很多个线程,大多数线程之间往往不是绝对独立的,比如说我们需要将A和B 两个线程的执行结果收集在一起然后显示在界面上,又或者比较典型的消费者-生产者模式,在这些场景下,线程间通信成了我们必须使用的手段,那么线程之间怎么通信呢?线程间通信方式,从实现本质来讲,主要可以分为两大类共享内存和消息传递。
2023-04-24 22:32:01
1264
原创 Java线程详解
线程是CPU调度和分配的基本单位,是操作系统可以识别的最小执行和调度单位,每个线程都有自己特定的独立的内存区域,当然也与其他线程共享堆内存,文件队列以及其他内核资源,Java虚拟机允许一个应用拥有多个线程并发工作。每个线程都有优先级,高优先级的线程会优先于低优先级的线程执行。。守护线程指的是专门为了服务其他线程而创建的线程,比如垃圾回收线程,就是最典型的守护线程,当所有非守护线程都执行完毕时(包括主线程),此时JVM退出,进而守护线程也就停止运行了。
2023-04-23 22:37:04
583
原创 Java-static那些事儿
执行Main中的测试代码,结果如下:可以看出,子类可以定义父类同名的静态方法,此时通过子类对象和子类调用的是子类声明的静态方法,当子类对象强转成父类对象或者通过父类,父类对象调用的是父类声明的静态方法。
2023-04-23 21:51:18
647
原创 Java内存模型详解
Java内存模型(Java Memory Model)是Java虚拟机规范定义的,用于屏蔽因不同程序/硬件/操作系统上内存访问的差异,确保程序运行与设计一致,Java内存模型定义了Java虚拟机在计算机内存中的工作方式,确定了在共享内存系统中,多线程程序读写操作行为的规范,其是JVM中的一部分。在上图中,当线程2对共享变量2进行修改时,共享变量2的内容如果还未同步到主存或者线程1获取共享变量2时,线程2修改操作未执行,都有可能导致线程1拿到的共享变量2的值与预期不同,进而导致程序异常。
2023-04-22 20:46:12
575
原创 final的那些事儿
关键词修饰类型作用final类,方法,变量修饰类,则类不可继承;修饰方法,则方法不可被子类重写;修饰变量,则变量只能初始化一次static内部类,方法,变量,代码段修饰内部类,则该类只能访问外部类的静态成员变量和方法,在Handler内存泄漏的修复方案中就有静态内部类的方式;修饰方法,则该方法可以直接通过类名访问修饰变量,则该变量可以直接通过类名访问,在类的实例中,静态变量共享同一份内存空间,故其具有全局性质。
2023-04-21 22:14:48
71
原创 JVM运行时内存分区
前文已经了解了对象的创建过程,对象内存空间的回收,在多线程环境下共享变量的同步等虚拟机知识,接下来我们来看下在虚拟机中是如何进行内存管理的,也就是Java虚拟机运行时内存分区。
2023-04-20 21:12:04
44
原创 Java对象管理
前文提到,Java对象创建后,会为对象分配一块内存空间,众所周知,设备的内存有限,也就意味着必须在一个合适的时机释放该内存空间,那么什么情况下这个对象的内存空间可以被释放呢?又是谁来执行该操作呢?早期计算机语言中,内存对象的创建和回收需要开发者根据逻辑控制。在Java中,内存空间的回收自动执行,由GC(Garbage Collection)实现,GC执行时机随机,大多数情况下,在JVM内存不足的情况下,会触发GC回收内存。那么GC如何判断对象是否可回收呢?通过对象回收算法。
2023-04-18 21:38:45
133
原创 类加载器-ClassLoader
前文说到其主要是用来进行.class文件的加载,创建Class对象,那么应该怎么自定义呢?自定义核心在于findClass方法的实现,在findClass方法中按照我们的期望进行类及资源的查找,查找完成后通过函数来定义Class字节流即可。// 所要加载的路径Path private String mPath;try {// 使用class文件流数据定义Class return defineClass(name , b , 0 , b . length);
2023-04-16 12:27:45
252
原创 Java对象
需要注意的是Java对象和VM内部对象都具有共同的对象头。在new指令执行完成后,也就意味着在内存中我们拥有了一个类的实例对象,到此就会执行我们编写的构造函数,根据开发人员的设计进行初始化,使得对象的状态符合开发人员预期,init函数执行完成后,一个Java对象的创建也就完成了。对于Java虚拟机而言,new指令意味着创建普通对象,该指令接受一个操作数,指向常量池中的一个引用,该引用用于指示要创建的对象类型,以前文代码为例,#2位置为new指令接受参数,其指向的是Person这个类,如下图。
2023-04-15 21:41:18
338
原创 Java对象
需要注意的是Java对象和VM内部对象都具有共同的对象头。在new指令执行完成后,也就意味着在内存中我们拥有了一个类的实例对象,到此就会执行我们编写的构造函数,根据开发人员的设计进行初始化,使得对象的状态符合开发人员预期,init函数执行完成后,一个Java对象的创建也就完成了。对于Java虚拟机而言,new指令意味着创建普通对象,该指令接受一个操作数,指向常量池中的一个引用,该引用用于指示要创建的对象类型,以前文代码为例,#2位置为new指令接受参数,其指向的是Person这个类,如下图。
2022-10-23 10:11:47
260
原创 Gradle编译报错:Could not create service of type ChecksumService using BuildSessionScopeServices.createCh
Gradle编译异常处理
2022-06-23 06:44:57
2631
2
原创 View绘制系列(5)-Canvas基础图形绘制
Canvas基础图形绘制上文中我们简单实现了使用自定义View绘制一个边长100的正方形这个需求,不知道同学们掌握的怎么样了?接下来我们看下自定义View中其他图形的绘制方式。下表中罗列了Canvas中绘图方法及说明(由于大多数方法都有多个重载实现,我们表中只列出比较常用的):方法名方法说明备注drawPoint(float x, float y, @NonNull Paint paint)绘制点Paint#setStrokeWidth(float width)设置点的大小
2020-11-02 20:30:43
474
原创 View绘制系列(4)-第一个自定义View
编写第一个自定义View为了后续文章中描述方便,我们把布局过程中的两个步骤单独分离,分别称为测量过程和布局过程。本篇文章的目标是在View内部(100,100)坐标处绘制一个边长为100的正方形,效果如下:怎么实现上面所说的效果呢?首先来考虑下如果是在现实生活中,我们要绘制一个顶点在(100,100),边长为100的正方形,我们需要什么呢?纸笔坐标系那么在View系统中是否有响应的抽象实现呢?如果有的话,绘制工作就变的异常简单了。首先来看下坐标系,这个肯定有啊,我们在View
2020-11-02 20:28:59
139
原创 View绘制系列(3)-自定义View简介
自定义View简介经过前面两篇文章的介绍,相信大多数同学已经清楚的认识了View,那么我们来看下自定义View这个主题,在小册简介中,我们已经描述了自定义View的目的,同学们还记得吗?用于解决使用系统控件实现不了或实现比较复杂的UI效果。在View简介部分,我们看到不管是XXXLayout还是XXXView,这些系统组件都直接或间接继承自View,那么自定义View的方式自然也有区分,根据继承父类的不同,我们大致可以将自定义View分为三类:继承自View继承自ViewGroup继承自已有控件
2020-11-02 20:25:16
88
原创 View绘制02-View生命周期
View生命周期在View简介之后,我们已经清楚的认识到View的基本概念:View是屏幕上的一块用于绘制和用户交互的矩形区域View是一个类,该类对象在View树创建或者我们使用java new关键词调用构造函数时创建了解C++的小伙伴们肯定都听过构造函数和析构函数这两个名词,通过构造函数我们可以生成一个类对象,通过析构函数我们可以完成一个对象的销毁,那么对于同样面对对象的Java而言,其是否有相似的机制?当然有,在Java中,我们通过构造函数进行对象创建,而对象的销毁由Java GC(全称G
2020-10-25 21:07:44
216
原创 View绘制01-Android渲染系统中的View
Android渲染系统中的View对于初级开发者而言,在面试中,经常会和面试官聊到Android四大组件,聊到Activity,其中回答最纯熟的一句话就是:Activity的作用是应用与用户之间交互的重要组件那么Activity之交互功能又是怎么实现的呢?答案不言而喻-View我们在Activity onCreate的时候调用setContentView方法为Activity设置布局,实际上就相当于对用户开放了多个交互接口,用户可以通过布局中一个一个的View进行自己想要的操作,我们也可以通过V
2020-10-24 12:12:57
324
原创 Windows Running “flutter pub get“ in XXX卡死
Running “flutter pub get” in XXX卡死的主要原因是因为网络访问问题,我们可以通过设置FlutterIO.cn来规避,具体操作如下:右键我的电脑->属性->高级系统设置->环境变量,添加环境变量,FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn,PUB_HOSTED_URL=https://pub.flutter-io.cn如下图所示:打开项目执行pub get,如果发现startup l
2020-07-07 19:07:01
2197
原创 appComponentFactory not found in package android
这里写自定义目录标题问题原因解决方案问题原因项目中appcompat包版本冲突解决方案统一项目内support相关包版本,在项目的build.gradle目录下,添加如下内容: ext { supportlib_version = 'X.X.X' } subprojects { project.configurations.all { resolutionStrategy.eachDependency { details -
2020-06-06 11:32:12
495
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人