Rinc

回顾 2017

今年个人技术发展最大的变化,就是终于有机会全身心投入到 iOS 开发了。主要两点收获:

  • 熟悉了 iOS 交叉编译,及 C/C++ 代码跨平台移植;

  • 熟悉了主流局域网设备发现方式,顺便复习了子网掩码、UDP 广播/多播等网络知识,并做了 兼容多平台的 UDP 方式实现;核心代码采用纯 C 语言实现,说实话毕业后好久没写 C 语言了,欢迎大家提 issue 或者 fork;

后面也会将主要精力用于对 iOS 的深入学习积累,当然也会保持对 AR/VR/AI 等的持续关注,有机会也会去深入学习。

阅读全文

iOS 引用 C/C++ 项目:平台差异导致的代码移植

#iOS #C++ #Clang #epoll #kqueue #pthread

由于 Linux(包括 Android)在嵌入式和服务端的流行,很多 C/C++ 代码都是专为 Linux 而写;加上历史原因,很可能还是基于 GCC 编译;

而 iOS/MacOS 基于类 Unix 系统 BSD,并且从 2011 年的 OS X 10.7 开始,默认的 C++ Runtime 就从 GNU 的 libstdc++ 迁移到 LLVM 的 libc++,二者不完全二进制兼容(Xcode 编译时只能二选一);

同时编译器也从 GCC 切换到了 Clang,而 Clang 通常比 GCC 语法检查更严格:

Clang strives to both conform to current language standards (up to C11 and C++11) and also to implement many widely-used extensions available in other compilers, so that most correct code will “just work” when compiled with Clang.
However, Clang is more strict than other popular compilers, and may reject incorrect code that other compilers allow.

基于上述原因,我们需要对部分 C/C++ 代码做改动,以便移植到 iOS/MacOS 项目中。

下面仅梳理下最近项目中遇到的情况。

阅读全文

iOS 引用 C/C++ 项目:交叉编译与 Objective-C++

#iOS #Objective-C #C++ #CMake #Clang

最近终于有幸参与公司的 iOS 项目,其中有个 C/C++ 写的库需要调用;

之前对 Android JNI/NDK 调用 C/C++ 还算熟悉,但 iOS 混编 C/C++ 却是初次接触,各种被虐..

上个周末基本都在解决库的编译问题,爱人 Amble 也耐心帮我查资料、作分析,感动之余,决定把中途遇到的问题记录下来。

阅读全文

回顾 2016

今年的 GitHub 提交记录相当惨淡,学东西也基本是蜻蜓点水:

阅读全文

FileChannel 高速拷贝文件的秘密

#Android #Java #NIO #Linux #系统原理

最近在做性能优化,发现 Java NIO 中的 FileChannel 类的 transfer 相关方法,能显著提升文件拷贝速度(自测减少耗时 30-70% 左右)。

官方的说法是,利用了文件系统的缓存:

This method is potentially much more efficient than a simple loop that reads from the source channel and writes to this channel.
Many operating systems can transfer bytes directly from the source channel into the filesystem cache without actually copying them.

阅读全文

SQLite 并发读写问题

#Android #SQLite

Android 中对 SQLiteDatabase 多线程并发读写时,很容易抛出以下异常:

java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
阅读全文

回顾 2015

毕业工作三年,一直埋头应用层开发,专业理论知识有恢复出厂设置的危险,而且深感各方面提升都遇到了瓶颈;
而去年疯狂地尝试各种新技术,导致战线拉得太长;所以今年自然是回归主旋律、填坑为主:代码写得少,书看的多,总结归纳的多。
通过对基础理论的复习巩固和专业领域的深挖,不仅重新(初步)完善了知识体系,还顺利拿到鹅厂 offer,也算弥补了四年前校招的缺憾。

阅读全文

JNI 引用问题梳理

#JNI

最近项目中有个视频文件分块上传的模块,核心逻辑是 C/C++ 实现的,Android 上层调用自然又要写 JNI。

其中有个需求是 Native 层上传进度更新时需要回调 Java 代码,这里我用了 C++11 的 Lambda 表达式:

std::function<void(unsigned)> cxx_progress_callback;
if (jcallback) {
cxx_progress_callback = [&env, &jcallback]
(unsigned progress) -> void {
jclass jcallback_class = env->GetObjectClass(jcallback);
if (jcallback_class) {
jmethodID methodId = env->GetMethodID(jcallback_class, "onProgressChanged", "(I)V");
if (methodId) {
env->CallVoidMethod(jcallback, methodId, progress);
}
}
};
}
阅读全文

Java 内存分配与垃圾回收机制

#JVM

程序计数器:

  • 用于指示当前线程执行的指令行号,字节码解释器通过改变它的值选取下一条待执行的指令;

  • 分支、循环、跳转、异常处理、线程恢复都需要依赖它;

  • 它是线程私有的;

阅读全文

DexClassLoader 实现 Android 插件加载

#Android #Java

Java 中的 ClassLoader:

Java 中 ClassLoader 用于动态加载 Class 到 JVM,包含 BootstrapClassLoader(C++ 编写,用于加载系统核心类)、ExtClassLoader(用于加载 lib/ext/ 目录的扩展 API)、AppClassLoader(加载 CLASSPATH 目录下的类)。

双亲委托机制:

  • 任何自定义 ClassLoader 都必须继承 ClassLoader 抽象类,并指定其 parent 加载器,默认为 BootstrapClassLoader;

  • 任何自定义 ClassLoader 在加载一个类之前都会先委托其 parent 去加载,只有 parent 加载失败才会自己加载;

    • 这样既可以防止重复加载,又可以排除安全隐患(防止用户替换系统核心类);

    • 所以一般只需要重写 findClass()方法即可(在 parent 加载失败时调用);

  • 双亲委托机制是在 loadClass() 方法实现的,要想避开(自己验证安全性,比如 Tomcat 的 WebAppClassLoader),必须重写 loadClass() 方法;

阅读全文
上一页 下一页