-
java开源包1
2013-06-28 09:14:34JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
java开源包12
2013-06-28 10:14:45JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
Java资源包01
2016-08-31 09:16:25JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
vmx进程已提前退出_简单分析 App 进程 Crash 机制
2020-11-30 09:02:04杰杰_88链接:https://www.jianshu.com/p/ecd52cd90a4b声明:本文已获杰杰_88授权发表,转发等请联系原作者授权结论:App进程Crash,不是真正意义上的进程崩溃(对比native代码崩溃),是java代码运行抛出没人处理的...code小生 一个专注大前端领域的技术平台公众号回复
Android
加入安卓技术群作者:杰杰_88
链接:https://www.jianshu.com/p/ecd52cd90a4b
声明:本文已获杰杰_88
授权发表,转发等请联系原作者授权结论:App进程Crash,不是真正意义上的进程崩溃(对比native代码崩溃),是java代码运行抛出没人处理的异常后,App自己把自己Kill掉了。
工作中遇到后台Service挂掉后(弹出停止运行),很久没有重启,分析log发现进程抛出FATAL EXCEPTION后并没有被杀,很久后才被杀掉重启,迷惑,遂看看具体的App挂掉流程是什么样的。
表象
当一个Android App进程因为各种原因抛出异常而没有被catch处理的时候,在用户看来,就会看到一个“某某已停止运行”的对话框,之前我一般认为该app进程已经挂掉。
实际上
以前在看到“某某已停止运行”时,一直认为对应进程也同时结束,没有仔细分析过整个App停止运行的机制,其实,停止运行对话框弹出的时候,进程还没有完全退出,真正的退出是进程将自己kill掉的时候。下面就记录下从App抛出没有catch的异常到该进程真正灰飞烟灭的整个过程。
App进程的创建
要分析一个app进程是怎么没的,先看看app进程是怎么来的。
关键代码
App进程创建流程:
App进程启动流程.png frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);frameworks/base/core/java/android/os/ZygoteProcess.java
//ZygoteState维护了与Zygote进程通过Socket的连接
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(mSocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList args)throws ZygoteStartFailedEx {
try {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
int sz = args.size();
for (int i = 0; i
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
/**
* See com.android.internal.os.SystemZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
Process.ProcessStartResult result = new Process.ProcessStartResult();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}zygoteSendArgsAndGetResult方法通过LocalSocket发送的命令被Zygote接收到:
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);此处fork出真正的app进程,然后在fork出的子进程中执行命令:
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
null /* classLoader */);执行的命令:
最终会从ActivityThread.java 的main函数进入,开始App的生命周期
*RuntimeInit.commonInit()
上面流程中,App进程fork出来后,执行此函数:
RuntimeInit.commonInit()
其中:
Thread.setUncaughtExceptionPreHandler(new LoggingHandler());
Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler());/**
* Dispatch an uncaught exception to the handler. This method is
* intended to be called only by the runtime and by tests.
*
* @hide
*/
// @VisibleForTesting (would be private if not for tests)
public final void dispatchUncaughtException(Throwable e) {
Thread.UncaughtExceptionHandler initialUeh =
Thread.getUncaughtExceptionPreHandler();
if (initialUeh != null) {
try {
initialUeh.uncaughtException(this, e);
} catch (RuntimeException | Error ignored) {
// Throwables thrown by the initial handler are ignored
}
}
getUncaughtExceptionHandler().uncaughtException(this, e);
}setUncaughtExceptionPreHandler设置“未捕获异常预处理程序”为loggingHandler,setDefaultUncaughtExceptionHandler设置真正的“未捕获异常默认处理程序”为KillApplicationHandler,按字面意思以及函数dispatchUncaughtException理解,发生异常时,先调用loggingHandler处理异常,再调用KillApplicationHandler处理。loggingHandler就是用来打印FATAL EXCEPTION以及trace的:
E AndroidRuntime: FATAL EXCEPTION: main
KillApplicationHandler:
/**
* Handle application death from an uncaught exception. The framework
* catches these for the main threads, so this should only matter for
* threads created by applications. Before this method runs,
* {@link LoggingHandler} will already have logged details.
*/
private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
try {
// Don't re-enter -- avoid infinite loops if crash-reporting crashes.
if (mCrashing) return;
mCrashing = true;
// Try to end profiling. If a profiler is running at this point, and we kill the
// process (below), the in-memory buffer will be lost. So try to stop, which will
// flush the buffer. (This makes method trace profiling useful to debug crashes.)
if (ActivityThread.currentActivityThread() != null) {
ActivityThread.currentActivityThread().stopProfiling();
}
final String processName = ActivityThread.currentProcessName();
if (processName != null) {
if (Build.IS_USERDEBUG && processName.equals(SystemProperties.get("persist.debug.process"))) {
Log.w(TAG, "process: " + processName + " crash message is skip");
return;
}
}
// Bring up crash dialog, wait for it to be dismissed
ActivityManager.getService().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
} catch (Throwable t2) {
if (t2 instanceof DeadObjectException) {
// System process is dead; ignore
} else {
try {
Clog_e(TAG, "Error reporting crash", t2);
} catch (Throwable t3) {
// Even Clog_e() fails! Oh well.
}
}
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
}
}这里通过如下代码和ActivityManagerService交互弹出“停止运行”对话框,注意注释,对话框消失后才会继续往下执行。
// Bring up crash dialog, wait for it to be dismissed
ActivityManager.getService().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));在ActivityManagerService,最终会停在如下代码处:
AppErrors.java crashApplicationInner():
synchronized (mService) {
/**
* If crash is handled by instance of {@link android.app.IActivityController},
* finish now and don't show the app error dialog.
*/
if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
timeMillis, callingPid, callingUid)) {
return;
}
/**
* If this process was running instrumentation, finish now - it will be handled in
* {@link ActivityManagerService#handleAppDiedLocked}.
*/
if (r != null && r.instr != null) {
return;
}
// Log crash in battery stats.
if (r != null) {
mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
}
AppErrorDialog.Data data = new AppErrorDialog.Data();
data.result = result;
data.proc = r;
// If we can't identify the process or it's already exceeded its crash quota,
// quit right away without showing a crash dialog.
if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
return;
}
final Message msg = Message.obtain();
msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
task = data.task;
msg.obj = data;
mService.mUiHandler.sendMessage(msg);
}
int res = result.get();result为AppErrorResult类型,result.get()会wait(),block当前Binder调用,等待对应的notify;前面的代码就是弹出“停止运行”的对话框:AppErrorDialog,result会随data传入AppErrorDialog,dismiss时调用result.set(),唤醒刚才Binder线程的wait:
AppErrorResult
final class AppErrorResult {
public void set(int res) {
synchronized (this) {
mHasResult = true;
mResult = res;
notifyAll();
}
}
public int get() {
synchronized (this) {
while (!mHasResult) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mResult;
}
boolean mHasResult = false;
int mResult;
}然后进行后面的处理Binder调用返回后,App进程中才最终会杀死自己:
finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}注意到,在AppErrorDialog构造函数中:
// After the timeout, pretend the user clicked the quit button
mHandler.sendMessageDelayed(
mHandler.obtainMessage(TIMEOUT),
DISMISS_TIMEOUT)如果用户一直没有理睬,会在5分钟后返回,可以注意如下log:
Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
在超时后才返回,就会导致 app 进程在 crash 状态下存在 5 分钟之久,除了异常的线程,其他线程还会努力工作,有可能会有些奇怪的事情发生。应该挂掉重启的,由于进程没有被杀死,
ActivityManagerService
收不到binderDied
消息,也会在超时之前一直得不到重启。相关阅读
1 你知道 Android 为什么会 Crash 吗
2 ANR 问题一般解决思路
3 Android 一次完美的跨进程服务共享实践
4 6. Jetpack---Paging你知道怎样上拉加载吗?
5 三年 Android 经验面经如果你有写博客的好习惯欢迎投稿
点个在看,小生感恩❤️
-
java开源包101
2016-07-13 10:11:08JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
java开源包11
2013-06-28 10:10:38JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
java开源包6
2013-06-28 09:48:32JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
java开源包10
2013-06-28 10:06:40JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
java开源包8
2013-06-28 09:55:26JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
java开源包9
2013-06-28 09:58:55JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
java开源包7
2013-06-28 09:52:16JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于... -
(一)多线程基础总结——轻松理解程序、进程、线程的区别和联系
2019-01-07 13:55:141.1 多线程是Java语言的重要特性。 我们可以流畅的点击软件或者游戏中的各种按钮,其实,底层就是多线程的应用。UI界面的主线程绘制界面,如果有一个耗时的操作发生则启动新的线程,完全不影响主线程的工作。当这...1.1 多线程是Java语言的重要特性。 我们可以流畅的点击软件或者游戏中的各种按钮,其实,底层就是多线程的应用。UI界面的主线程绘制界面,如果有一个耗时的操作发生则启动新的线程,完全不影响主线程的工作。当这个线程工作完毕后,再更新到主界面上。 我们可以上百人、上千人、上万人同时访问某个网站,其实,也是基于网站服务器的多线程原理。如果没有多线程,服务器处理速度会极大降低。
多线程应用于计算机的各个方面,但是对于初学者的我们,我们只需掌握基本的概念即可。在入门阶段,暂时没有必要钻研过深。今天就和大家一起讨论一下多线程。。。
1.2 在计算机中通常有程序,进程,线程的名词概念,那这三个词是什么含义呢?好,接下来我们先着手理解这三个名词是什么意思
- 程序:“程序(Program)”是一个静态的概念,一般对应于操作系统中的一个可执行文件,比如:我们要启动酷狗听音乐,则对应酷狗的可执行程序。当我们双击酷狗,则加载程序到内存中,开始执行该程序,于是产生了“进程”。
- 进程:执行中的程序叫做进程(Process),是一个动态的概念。现代的操作系统都可以同时启动多个进程。比如:我们在用酷狗听音乐,也可以使用eclipse写代码,也可以同时用浏览器查看网页。
进程具有如下特点:
1. 进程是程序的一次动态执行过程, 占用特定的地址空间。
2. 每个进程由3部分组成:cpu、data、code。每个进程都是独立的,保有自己的cpu时间,代码和数据,即便用同一份程序产生好几个进程,它们之间还是拥有自己的这3样东西,这样的缺点是:浪费内存,cpu的负担较重。
3. 多任务(Multitasking)操作系统将CPU时间动态地划分给每个进程,操作系统同时执行多个进程,每个进程独立运行。以进程的观点来看,它会以为自己独占CPU的使用权。
4. 进程的查看
Windows系统: Ctrl+Alt+Del,启动任务管理器即可查看所有进程。
- 线程:一个进程可以产生多个线程。同多个进程可以共享操作系统的某些资源一样,同一进程的多个线程也可以共享此进程的某些资源(比如:代码、数据),所以线程又被称为轻量级进程(lightweight process)。
线程的特点:
1. 一个进程内部的一个执行单元,它是程序中的一个单一的顺序控制流程。
2. 一个进程可拥有多个并行的(concurrent)线程。
3. 一个进程中的多个线程共享相同的内存单元/内存地址空间,可以访问相同的变量和对象,而且它们从同一堆中分配对象并进行通信、数据交换和同步操作。
4. 线程的启动、中断、消亡,消耗的资源非常少。
1.3 相信大家对程序、进程、线程的概念都做到心中有数了,那接下来我们谈一下它们三者的区别,首先:
- 线程和进程的区别:
1. 每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。
2. 线程可以看成是轻量级的进程,属于同一进程的线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
3. 线程和进程最根本的区别在于:进程是资源分配的单位,线程是调度和执行的单位。
4. 多进程: 在操作系统中能同时运行多个任务(程序)。
5. 多线程: 在同一应用程序中有多个顺序流同时执行。
6. 线程是进程的一部分,所以线程有的时候被称为轻量级进程。
7. 一个没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个线程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。
8. 系统在运行的时候会为每个进程分配不同的内存区域,但是不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源。那就是说,除了CPU之外(线程在运行的时候要占用CPU资源),计算机内部的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
- 进程与程序的区别:
程序是一组指令的集合,它是静态的实体,没有执行的含义。而进程是一个动态的实体,有自己的生命周期。一般说来,一个进程肯定与一个程序相对应,并且只有一个,但是一个程序可以有多个进程,或者一个进程都没有。除此之外,进程还有并发性和交往性。简单地说,进程是程序的一部分,程序运行的时候会产生进程。
相信各位初学者对程序、进程、线程的含义应该可以轻松理解了吧,喜欢的各位伙伴欢迎关注博主,可以及时获取最新博文和动态哦
ps思考:比咱们优秀的人,为什么比咱们还努力?
-
JAVA上百实例源码以及开源项目
2016-01-03 17:37:40Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,... -
SIM卡 --- 联系人查询过程分析
2018-01-05 19:14:16在前面已经论述过, SIM卡中的联系人是保存在单独的数据库中,其对应的Provider为IccProvider,在packages\services\Telephony 路径下,也就是phone进程中。并且,增删改查直接看jar包中的IccProvider类就可以了, ...6.3 联系人操作
在前面已经论述过, SIM卡中的联系人是保存在单独的数据库中,其对应的Provider为IccProvider,在packages\services\Telephony 路径下,也就是phone进程中。并且,增删改查直接看jar包中的IccProvider类就可以了, IccProvider路径如下,
frameworks/opt/telephony/src/java/com/android/internal/telephony/IccProvider.java
IccProvider中对应的4个增删改查的方法分别对应, query/ insert/ delete/ update 方法。
其中insert/ delete/ update 三个方法都是调用updateIccRecordInEf方法实现。
3.1 查询
IccProvider中有3种类型的电话本,分别是ADN/FDN/SDN, FDN/SDN 用的比较少, sim卡上的电话本就是ADN。当然,处理过程也是大同小异,只看AND的处理。
IccProvider的query方法主要逻辑就是根据不同类型分别调用loadFromEf方法进行处理。
对AND的处理如下,
case ADN: //默认SIM卡 return loadFromEf(IccConstants.EF_ADN, SubscriptionManager.getDefaultSubId()); case ADN_SUB: // 双卡双待 return loadFromEf(IccConstants.EF_ADN, getRequestSubId(url));
调用流程图如下,
loadFromEf方法主要逻辑如下,
1,调用UiccPhoneBookController的getAdnRecordsInEfForSubscriber方法进行查询,将结果封装成AdnRecord,
List<AdnRecord> adnRecords = null; try { IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface( ServiceManager.getService("simphonebook")); if (iccIpb != null) { adnRecords = iccIpb.getAdnRecordsInEfForSubscriber(subId, efType); } •••
2,调用loadRecord方法将查询结果封装为MatrixCursor对象,并返回,
if (adnRecords != null) { // Load the results final int N = adnRecords.size(); final MatrixCursor cursor = new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES, N); log("adnRecords.size=" + N); for (int i = 0; i < N ; i++) { loadRecord(adnRecords.get(i), cursor, i); } return cursor;
3,如果查询结果为空,
return new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES);
主要分为2个部分,分别进行阐述。loadRecord方法很简单,主要逻辑如下,
1,首先获取联系人的信息,
String alphaTag = record.getAlphaTag(); String number = record.getNumber(); String[] anrs =record.getAdditionalNumbers();
2,然后将信息封装在
Object[] contact = new Object[5]; ••• contact[0] = alphaTag; contact[1] = number; •••
3,最后将contact封装为MatrixCursor对象,
cursor.addRow(contact);
1.1查询分析
"simphonebook"对应的系统服务为UiccPhoneBookController,UiccPhoneBookController定义如下,
public class UiccPhoneBookController extends IIccPhoneBook.Stub {
构造方法如下,
if (ServiceManager.getService("simphonebook") == null) { ServiceManager.addService("simphonebook", this); } mPhone = phone;
getAdnRecordsInEfForSubscriber方法如下,
1,调用getIccPhoneBookInterfaceManagerProxy方法获取IccPhoneBookInterfaceManagerProxy对象,
IccPhoneBookInterfaceManagerProxy iccPbkIntMgrProxy = getIccPhoneBookInterfaceManagerProxy(subId);
2,调用IccPhoneBookInterfaceManagerProxy对象的getAdnRecordsInEf方法,
return iccPbkIntMgrProxy.getAdnRecordsInEf(efid);
getAdnRecordsInEf方法如下,
return mIccPhoneBookInterfaceManager.getAdnRecordsInEf(efid);
IccPhoneBookInterfaceManager只是一个抽象类,子类分别为CDMA卡对应的RuimPhoneBookInterfaceManager对象,GSM卡对应的SimPhoneBookInterfaceManager对象。
无论哪个对象, getAdnRecordsInEf都是在IccPhoneBookInterfaceManager中实现的。
getAdnRecordsInEf方法逻辑如下,
1,给代码块加锁
synchronized(mLock) {
2,检查当前线程不是UI线程,因此,Contentprovider的操作一般都在子线程中进行,
checkThread();
3,构造回调处理消息, EVENT_LOAD_DONE,
AtomicBoolean status = new AtomicBoolean(false); Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE, status);
4,调用AdnRecordCache的requestLoadAllAdnLike方法处理,
mAdnCache.requestLoadAllAdnLike(efid, mAdnCache.extensionEfForEf(efid), null, response);
5,当前线程进行休眠,
waitForResult(status);
6,当前线程唤醒后,调用getAdnRecordsInEf方法返回结果,
return getAdnRecordsInEf(IccConstants.EF_ADN);
注意,这里面有个休眠唤醒的操作来进行子线程的同步。
AdnRecordCache的requestLoadAllAdnLike方法主要逻辑如下,
1,如果是EF_PBR类型,调用UsimPhoneBookManager方法的loadEfFilesFromUsim/ loadEfFilesFromUsim方法加载,否则调用getRecordsIfLoaded方法直接获取,
result = mUsimPhoneBookManager.loadEfFilesFromUsim(); ••• result = getRecordsIfLoaded(efid);
如果result不为空,说明结果已经加载过了,已经缓存了,直接返回,
if (result != null) { if (response != null) { AsyncResult.forMessage(response).result = result; response.sendToTarget(); } return; }
2,如果已经开始查询了,就直接返回,
waiters = mAdnLikeWaiters.get(efid); if (waiters != null) { ••• waiters.add(response); return; }
3,最后调用AdnRecordLoader的loadAllFromEF方法进行加载,
waiters = new ArrayList<Message>(); waiters.add(response); mAdnLikeWaiters.put(efid, waiters); ••• new AdnRecordLoader(mFh).loadAllFromEF(efid, extensionEf, path, obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE, efid, extensionEf));
当然,加载完成之后的回调处理消息为EVENT_LOAD_ALL_ADN_LIKE_DONE,
AdnRecordLoader的loadAllFromEF方法如下,
mEf = ef; mExtensionEF = extensionEF; mPath = path; mUserResponse = response; mFh.getEFLinearRecordSize( mExtensionEF, getEFPath(mExtensionEF), obtainMessage(EVENT_EFEXT1_LINEAR_RECORD_SIZE_DONE, path));
调用IccFileHandler的getEFLinearRecordSize方法进行处理,并且回到消息为EVENT_EFEXT1_LINEAR_RECORD_SIZE_DONE
IccFileHandler也是一个抽象类,但是实现了getEFLinearRecordSize方法,该方法逻辑如下,
String efPath = (path == null) ? getEFPath(fileid) : path; Message response = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE, new LoadLinearFixedContext(fileid, efPath, onLoaded)); mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, efPath, 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
调用RIL的iccIOForApp方法进行加载, iccIOForApp方法会向rild守护进程发送RIL_REQUEST_SIM_IO消息,到modem侧进行处理。回调处理消息为EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE。
-
JAVA上百实例源码以及开源项目源代码
2016-09-17 21:58:33Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,... -
java 面试题 总结
2009-09-16 08:45:34它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是... -
Java网络编程_01
2020-08-13 19:46:46跨机进程通信 什么是网络、计算机网络的构成是什么? 什么是网络编程? 什么是网络? (1) 在计算机领域中,网络是信息传输、接收、共享的虚拟平台 (2) 通过网络可以把各个点、面、体的信息联系到一起,从而实现...
什么是网络编程
- 跨机进程通信
- 什么是网络、计算机网络的构成是什么?
- 什么是网络编程?
- 什么是网络?
(1) 在计算机领域中,网络是信息传输、接收、共享的虚拟平台
(2) 通过网络可以把各个点、面、体的信息联系到一起,从而实现这些资源的共 - 网络是人类发展史来最重要的发明,提高了科技和人类社会的发展
局域网
什么是网络编程
- 网络编程从大的方面说就是对信息的发送与接收
- 通过操作相应的API调用计算机硬件资源,并利用传输管道(网线、光、无线电波)进行数据交换的过程
- 更为具体的涉及:网络模型、套接字、数据包
OSI七层网络模型
- 基础层:物理层、数据链路层、网络层
- 传输层:TCP协议、UDP协议、Socket
- 高基层:会话层、表示层、应用层
Scoket与TCP、UDP
- 什么是Socket?
(1) 简单来说Socket就是IP地址与端口号的结合协议:RFC 793
(2) 一种地址与端口的结合描述协议
(3) TCP/IP协议的相关API的总称;是网络API的集合实现
(4) 涵盖了:Stream Socket / Datagram Socket - Socket的作用与组成
(1) 在网络传输中用于唯一标识两个断点之间的链接
(2) 端点:包括IP与端口
(3) 4个要素:客户端IP地址、客户端端口、服务器端IP地址、服务器端端口 - Socket之TCP
(1) TCP是面向连接的通信协议
(2) 通过三次握手建立连接,通讯完成时需要拆除连接
(3) 由于TCP是面向连接的,所以只能用于端到端的通讯 - Scoket之UDP
(1) UDP是面向无连接的通讯协议
(2) UDP的数据包括目的端口号和源端口号信息
(3) 由于通讯不需要连接,所以可以实现广播,并不局限于端到端 - TCP传输图解
- UDP传输图解
- C/S模型:
(1) 在TCP/IP协议中,两个进程间通信的主要模式为:C/S通信
(2) 主要目的:协同网络中的计算机资源、服务模式、进程间数据共享
(3) 常见的:FTP、SMTP、HTTP
Socket TCP客户端:BIO
todo()
Socket TCP服务器:BIO
-
java中的多线程详解
2020-10-27 22:46:312、进程与线程之间的区别与联系 线程与线程之间共享堆内存和方法区内存,但是不共享栈内存,每个栈与每个栈之间,互不干扰,各自执行各自的,这就是多线程并发。 3、线程与栈的关系内存图 4、其实单核... -
常见面试题的基础总结(Java多线程篇)
2019-06-13 11:36:39由于这些内容都是比较早之前进行的整理的,所以有的部分是参考了他人的博文,但是由于是之前找的,所以具体的博文链接找不到了,如果原博主看到这个文章或者有人知道其中部分内容的原博文,请与我联系,我将加上原... -
JAVA面试题最全集
2010-03-13 13:09:10简述 Java Server Page 和 Servlet 的联系和区别。 33.简述synchronized和java.util.concurrent.locks.Lock的异同 ? 34.EJB规范规定EJB中禁止的操作有哪些? 35.java除了8种基本类型外,在虚拟机里还有哪一种,... -
Java多线程(三)、线程同步
2014-01-09 16:18:49Java多线程(三)、线程同步 分类: javaSE综合知识点 2012-09-18 17:59 564人阅读 评论(0) 收藏 举报 在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系。可是... -
异步时代-java的协程路在何方
2019-09-30 07:37:49面试官:行,你先回去吧,到时候电话联系 。。。。。。。。 很尴尬,但是事实是,很大一部分的程序员不知道协程是啥玩意,更大一部分的程序员,项目中没用到协程。 先介绍下协程吧。 计算机有进程,线程和协程... -
超级有影响力霸气的Java面试题大全文档
2012-07-18 09:47:04它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是... -
Android5.1Telecomm层通话去电流程两路进程分析之二拨号过程显示通话界面过程分析
2016-01-01 17:01:06至于这个过程做了什么可以参考我的另一篇文章--“Contacts模块拨号加载联系人信息流程”,这其中有详细的分析,我们直接跟踪到InCallController.java(packages/services/Telecomm)中的onCallAdded方法: ... -
PDF文档的内容均为手打,有任何的不懂都可以直接来问我(公众号有我的私人的联系方式)。扫下方二维码或者微信搜索Java3y,在公众号下回复「888」即可获取!! 从Java基础、JavaWeb基础到常用的框架再到面试题都...
-
Android开发权威指南.(人民邮电.李宁).pdf
2016-06-01 12:41:246.2.3 QuickContactBadge与联系人菜单 189 6.3 小结 192 第7章 友好地互动交流——信息提醒(对话框、Toast与Notification)193 7.1 对话框的基本用法 193 7.1.1 带2个按钮(确认/取消)的对话框 193 7.1.2 带... -
一文弄懂JVM内存结构,垃圾回收器和垃圾回收算法
2020-02-13 14:04:23声明:本文从知乎上部分热门文章做二次整理,希望可以帮助更多的人,如有侵权,请联系删除。 jvm 概述: jvm: java virtual machine, 用于把我们写的那些不能直接被程序识别的java代码,翻译给操作系统,告诉他... -
第二篇
2017-11-27 18:40:02先说一下程序,进程,线程之间的区别还有联系 程序:程序是为实现特定目标或解决特定问题而用计算机语言编写的命令序列的集合。 说白点就是静态代码,是应用程序执行的蓝本。 进程:进程是指一 -
基础-1 系统的架构
2017-01-16 14:22:044层架构:① Applications 原生的应用程序:浏览器、桌面、联系人等② Application Framework 中间介,java代码调用底层c代码,提供各种管理器③ Libraries(c代码库),Android Runtime(Dalvik VM、Libraries C)...