当前位置:网站首页>StrictMode卡顿与泄漏检测-StrictMode原理(2)
StrictMode卡顿与泄漏检测-StrictMode原理(2)
2022-07-01 00:40:00 【怪叔叔萝莉控】
2. StrictMode关闭检测原理
StrictMode的关闭检测其实是比较简单的,基本上就是在开启的时候埋桩,释放的时候检测桩子是否有关闭,没有关闭则检测为泄漏。
2.1 CloseGuard
这里有一个预备知识,那就是CloseGuard,它是一个StrictMode专门为了处理此类事情的类,主要包括三个函数:
- open 开始埋桩
- close 拆桩
- warnIfOpen 爆炸
SystemApi(client = MODULE_LIBRARIES)
@libcore.api.IntraCoreApi
public final class CloseGuard {
private static volatile boolean stackAndTrackingEnabled = true;
private static volatile Reporter reporter = new DefaultReporter();
private static volatile Tracker currentTracker = null; // Disabled by default.
@UnsupportedAppUsage
@SystemApi(client = MODULE_LIBRARIES)
public static void setEnabled(boolean enabled) {
CloseGuard.stackAndTrackingEnabled = enabled;
}
public static boolean isEnabled() {
return stackAndTrackingEnabled;
}
@UnsupportedAppUsage(trackingBug=111170242)
@SystemApi(client = MODULE_LIBRARIES)
@libcore.api.IntraCoreApi
public void open(String closer) {
openWithCallSite(closer, null /* callsite */);
}
//关闭之前,
@UnsupportedAppUsage
@SystemApi(client = MODULE_LIBRARIES)
@libcore.api.IntraCoreApi
public void close() {
Tracker tracker = currentTracker;
if (tracker != null && closerNameOrAllocationInfo instanceof Throwable) {
// Invoke tracker on close only if we invoked it on open. Tracker may have changed.
tracker.close((Throwable) closerNameOrAllocationInfo);
}
closerNameOrAllocationInfo = null;
}
public void warnIfOpen() {
if (closerNameOrAllocationInfo != null) {
if (closerNameOrAllocationInfo instanceof Throwable) {
reporter.report(MESSAGE, (Throwable) closerNameOrAllocationInfo);
} else if (stackAndTrackingEnabled) {
reporter.report(MESSAGE + " Callsite: " + closerNameOrAllocationInfo);
} else {
System.logW("A resource failed to call "
+ (String) closerNameOrAllocationInfo + ". ");
}
}
}
}
2.1 IO关闭检测
回顾一下之前的例子
findViewById<Button>(R.id.io_not_close_btn).setOnClickListener {
var outputStream = FileOutputStream(File(getExternalFilesDir("")?.path + "hello.json"))
outputStream.write("hello world".toByteArray())
outputStream = FileOutputStream(File(getExternalFilesDir("")?.path + "hello.json"))
Runtime.getRuntime().gc()
Runtime.getRuntime().gc()
}
埋炸弹 -首先来看看构造函数:
private final CloseGuard guard = CloseGuard.get();
public FileOutputStream(File file, boolean append)
throws FileNotFoundException
{
String name = (file != null ? file.getPath() : null);
.......
// Android-added: CloseGuard support. Android添加的
guard.open("close");
}
拆炸弹 - 关闭输出流
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
// Android-added: CloseGuard support.
guard.close();
}
爆炸 - 没有调用close便被回收
protected void finalize() throws IOException {
// Android-added: CloseGuard support.
if (guard != null) {
guard.warnIfOpen();
}
...
}
同理推断其他的流也会有其他的机制来检测泄漏。
2.2 IO卡顿检测
看卡顿前,我们需要先准备点预备知识,IO读取与写出的预备知识:
FileInputStream/FileOutputStream -> IOBridge -> ForwardingOs -> BlockGuardOS -> LibCore.OS
我们需要关注的主要在BlockGuardOS这一层,我们先看看源代码:
public class BlockGuardOs extends ForwardingOs {
@Override public FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
BlockGuard.getThreadPolicy().onReadFromDisk();//检测IO读
BlockGuard.getVmPolicy().onPathAccess(path);//检测VM策略路径访问
if ((flags & O_ACCMODE) != O_RDONLY) {
BlockGuard.getThreadPolicy().onWriteToDisk(); //检测IO写
}
....
}
@UnsupportedAppUsage
@Override public void close(FileDescriptor fd) throws ErrnoException {
try {
if (fd.isSocket$()) {
if (isLingerSocket(fd)) {
BlockGuard.getThreadPolicy().onNetwork(); //是否主线程访问网络
}
}
} catch (ErrnoException ignored) {
}
super.close(fd);
}
}
这里比较清晰的看到,BlockGuardOs内部代理了BlockGuard,每次调用函数前,都会检测一下是否有卡顿问题。最后再回到StrictMode.
public void onReadFromDisk() {
if ((mThreadPolicyMask & DETECT_THREAD_DISK_READ) == 0) {
return;
}
if (tooManyViolationsThisLoop()) {
return;
}
//这个函数里面会进行打印
startHandlingViolationException(new DiskReadViolation());
}
2.3 SqliteCursor泄漏检测
location:frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
protected void finalize() {
try {
// if the cursor hasn't been closed yet, close it first
if (mWindow != null) {
// Report original sql statement
if (StrictMode.vmSqliteObjectLeaksEnabled()) {
String sql = mQuery.getSql();
int len = sql.length();
StrictMode.onSqliteObjectLeaked(
"Finalizing a Cursor that has not been deactivated or closed. "
+ "database = " + mQuery.getDatabase().getLabel()
+ ", table = " + mEditTable
+ ", query = " + sql.substring(0, (len > 1000) ? 1000 : len),
null);
}
}
} finally {
super.finalize();
}
}
很明显就可以看出,当mWindow不为空时,会进行泄漏的消息上报。这里的window指的是cursor的查询窗口,执行过move函数会赋值
边栏推荐
- Join table query select generation
- C语言一点点(未来可会增加)
- The question of IBL precomputation is finally solved
- pull_ to_ refresh
- None of the following candidates is applicable because of a receiver type mismatch
- Orb-slam2 source code learning (II) map initialization
- 5. TPM module initialization
- Win11安装redis 数据库以及redis desktop manager的下载
- For the first time in more than 20 years! CVPR best student thesis awarded to Chinese college students!
- 酒旅板块复苏,亚朵继续上市梦,距离“新住宿经济第一股“还有多远?
猜你喜欢

DLS-42/6-4 DC110V双位置继电器

Analyze the maker education path integrating the essence of discipline

二十多年来第一次!CVPR最佳学生论文授予中国高校学生!

ORB-SLAM2源码学习(二)地图初始化

Oracle table creation and management

蒹葭苍苍,白露为霜。

Technical personnel advanced to draw a big picture of business, hand-in-hand teaching is coming

Analysis of blocktoken principle

機器人編程的培訓學科類原理

DLS-20型双位置继电器 220VDC
随机推荐
Analysis of blocktoken principle
C # generates PPK files in putty format (supports passphrase)
Cmu15445 (fall 2019) project 1 - buffer pool details
C语言一点点(未来可会增加)
Pytorch installs and uses GPU acceleration
(学习力+思考力) x 行动力,技术人成长的飞轮效应总结
Locking relay ydb-100, 100V
Document service design
ArrayList analysis 1-cycle, capacity expansion, version
[learning notes] simple DP
探索互联网时代STEAM教育创新之路
Chapter 53 overall understanding of procedures from the perspective of business logic implementation
Web compatibility testing of software testing
The longest selling mobile phone in China has been selling well since its launch, crushing iphone12
解析创客教育实践中的智慧原理
High quality pump SolidWorks model material recommended, not to be missed
Get screen height
ArrayList analysis 1-cycle, capacity expansion, version
Gavin's insight on the transformer live broadcast course - rasa project's actual banking financial BOT Intelligent Business Dialogue robot system startup, language understanding, dialogue decision-mak
Split the linked list [take next first and then cut the linked list to prevent chain breakage]