diff --git a/README.md b/README.md index 3f0c888..5e54586 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,15 @@ Android Notes --- -#### 常用组件 +#### Android + +##### 组件相关 1. [WebView](https://github.com/Omooo/Android-Notes/blob/master/blogs/WebView.md) 2. [RecyclerView](https://github.com/Omooo/Android-Notes/blob/master/blogs/RecyclerView.md) +3. [ViewPager](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/ViewPager.md) -#### 常见知识点 +##### 其他 1. Android 数据持久化 - [SharedPreferences](https://github.com/Omooo/Android-Notes/blob/master/blogs/SharedPreferences.md) @@ -16,6 +19,12 @@ Android Notes 3. [动画](https://github.com/Omooo/Android-Notes/blob/master/blogs/Animator.md) 4. [Context](https://github.com/Omooo/Android-Notes/blob/master/blogs/Context.md) 5. [Dalvik 与 ART](https://github.com/Omooo/Android-Notes/blob/master/blogs/Dalvik%20:%20ART.md) +6. [APT](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/APT.md) +7. [Bundle、ArrayMap、SparseArray](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Bundle.md) +8. [Hook 原来也就这么回事](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Hook.md) +9. [Serializable 与 Parceable](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Serializable%20%E4%B8%8E%20Parceable.md) +10. [轻松入门 Socket 编程](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Socket%20%E7%BC%96%E7%A8%8B.md) +11. [热修复](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/%E7%83%AD%E4%BF%AE%E5%A4%8D.md) #### 性能优化 @@ -33,10 +42,30 @@ Android Notes [注解 你需要知道的一切](https://github.com/Omooo/Android-Notes/blob/master/blogs/%E6%B3%A8%E8%A7%A3.md) +[异常 你需要知道的一切](https://github.com/Omooo/Android-Notes/blob/master/blogs/Java/%E5%BC%82%E5%B8%B8.md) + #### JVM [方法内联](https://github.com/Omooo/Android-Notes/blob/master/blogs/JVM/%E6%96%B9%E6%B3%95%E5%86%85%E8%81%94.md) +[一篇文章搞懂 锁](https://github.com/Omooo/Android-Notes/blob/master/blogs/Java/%E9%94%81.md) + +[UncaughtExceptionHandler](https://github.com/Omooo/Android-Notes/blob/master/blogs/Java/UncaughtExceptionHandler.md) + #### 设计模式 -[单例模式]() \ No newline at end of file +[单例模式]() + +[工厂模式](https://github.com/Omooo/Android-Notes/blob/master/blogs/DesignMode/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.md) + +[代理模式](https://github.com/Omooo/Android-Notes/blob/master/blogs/DesignMode/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F.md) + +[观察者模式](https://github.com/Omooo/Android-Notes/blob/master/blogs/DesignMode/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F.md) + +[Builder 建造者模式](https://github.com/Omooo/Android-Notes/blob/master/blogs/DesignMode/Builder%20%E5%BB%BA%E9%80%A0%E8%80%85%E6%A8%A1%E5%BC%8F.md) + +#### 数据结构和算法 + +[异或,原来这么有用](https://github.com/Omooo/Android-Notes/blob/master/blogs/Algorithm/%E5%BC%82%E6%88%96%E5%BA%94%E7%94%A8.md) + +[一篇文章搞定 HashMap](https://github.com/Omooo/Android-Notes/blob/master/blogs/Algorithm/HashMap.md) \ No newline at end of file diff --git a/blogs/Android/Activity.md b/blogs/Android/Activity.md new file mode 100644 index 0000000..30d0342 --- /dev/null +++ b/blogs/Android/Activity.md @@ -0,0 +1,18 @@ +--- +Activity +--- + +#### 目录 + +1. 思维导图 +2. 概述 +3. 生命周期 +4. 启动模式 +5. 重要方法 +6. 转场动画 +7. 参考 + +#### 思维导图 + +#### 概述 + diff --git a/blogs/Java/异常.md b/blogs/Java/异常.md index 02d25eb..c10b9ef 100644 --- a/blogs/Java/异常.md +++ b/blogs/Java/异常.md @@ -8,11 +8,12 @@ 2. 概述 3. 异常处理 4. 实现原理 -5. 参考 +5. Supressed 异常以及语法糖 +6. 参考 #### 思维导图 - +![](https://i.loli.net/2019/01/29/5c5064b27d2b7.png) #### 概述 @@ -42,6 +43,10 @@ try 代码块用来标记需要进行异常监控的代码,catch 代码块跟 异常实例的构造十分昂贵。这是由于在构造异常实例时,Java 虚拟机便需要生成该异常的栈轨迹(stack trace)。该操作会逐一访问当前线程的 Java 栈帧,并且记录下各种调试信息,包括栈帧所指向方法的名字,方法所在的类名、文件名,以及在代码中的第几行触发该异常。 +当然,在生成栈轨迹时,Java 虚拟机会忽略掉异常处理器以及填充栈帧的 Java 方法(Throwable.fillInStackTrace),直接从新建异常位置开始算起。 + +这里遍历堆栈的时候,并不用担心 inline 代码消除等编译优化对错误堆栈和代码对不上的情况,所以也就不需要先去优化之后在遍历。即时编译器生成的代码会保存原始的栈信息,以便去优化时能够复原,fillStackTrace 也会读取这些信息的,所以不需要去优化之后在 fill。 + 那么 Java 虚拟机是如何捕获异常的? 在编译生成的字节码中,每个方法都附带一个异常表。异常表中的每一个条目代表一个异常处理器,并且由 from 指针、to 指针、target 指针以及所捕获的异常类型构成。这些指针的值是字节码索引,用以定位字节码。 @@ -50,6 +55,85 @@ try 代码块用来标记需要进行异常监控的代码,catch 代码块跟 当程序触发异常时,Java 虚拟机会从上至下遍历异常表中的所有条目。当触发异常的字节码的索引值在某个异常表条目的监控范围内,Java 虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。Java 虚拟机会将控制流转移至该条目 target 指针指向的字节码。 +如果遍历完所有异常表条目,Java 虚拟机仍未匹配到异常处理器,那么它会弹出当前方法对应的 Java 栈帧,并且在调用者中重复上述操作。在最坏的情况下,Java 虚拟机需要遍历当前线程 Java 栈上所有方法的异常表。 + +finally 代码块的编译比较复杂,当前版本 Java 编译器的做法,是复制 finally 代码块的内容,分别放在 try-catch 代码块所有正常执行路径以及异常执行路径的出口中。 + +![](https://i.loli.net/2019/01/29/5c5059fb5251e.png) + +针对异常执行路径,Java 编译器会生成一个或多个异常表条目,监控整个 try-catch 代码块,并且捕获所有种类的异常。这些异常表条目的 target 指针将指向另一份复制的 finally 代码块。并且,在这个 finally 代码块的最后,Java 编译器会重新抛出所捕获的异常。 + +如果 catch 代码块捕获了异常,并且触发了另外一个异常,那么 finally 捕获并重抛的异常是哪个呢?答案是后者,也就是说原本的异常便会被忽略掉,这对于代码调试来说十分不利。 + +#### Supressed 异常以及语法糖 + +Java 7 引入了 Supressed 异常来解决这个问题,这个新特性允许开发人员将一个异常附于另一个异常之上。因此,抛出的异常可以附带多个异常的信息。 + +然鹅,Java 层面的 finally 代码块缺少指向所捕获异常的引用,所以这个新特性使用起来非常繁琐。 + +为此,Java 7 专门构造了一个名为 try-with-resources 的语法糖,在字节码层面自动使用 Supressed 异常。当然,该语法糖的主要目的并不是使用 Supressed 异常,而是精简资源打开关闭。 + +在 Java 7 之前,对于打开的资源,我们需要定义一个 finally 代码块,来确保该资源在正常或者异常执行状态情况下都能关闭。 + +资源的关闭操作本身容易触发异常。因此,如果同时打开多个资源,那么每一个资源都要对应一个独立的 try-finally 代码块,以保证每个资源都能关闭。这样一来,代码将会变得十分繁琐。 + +Java 7 的 try-with-resources 语法糖,极大的简化了上诉代码。程序可以在 try 关键字后声明并实例化实现了 AutoCloseable 接口的类,编译器将自动添加对应的 close 操作。在声明多个 AutoCloseable 实例的情况下,编译生成的字节码类似于上面手工编写代码的编译结果。与手工代码相比,try-with-resources 还会使用 Supressed 异常的功能,来避免原异常 “被消失”。 + +```java +public class Foo implements AutoCloseable { + private String name; + + public Foo(String name) { + this.name = name; + } + + @Override + public void close() throws Exception { + throw new RuntimeException(name); + } + + public static void main(String[] args) throws Exception { + try ( + Foo foo0 = new Foo("Foo0"); + Foo foo1 = new Foo("Foo1"); + Foo foo2 = new Foo("Foo2") + ) { + throw new RuntimeException(""); + } + } +} +//输出: +Exception in thread "main" java.lang.RuntimeException: + at annotation.Foo.main(Foo.java:21) + Suppressed: java.lang.RuntimeException: Foo2 + at annotation.Foo.close(Foo.java:12) + at annotation.Foo.$closeResource(Foo.java:22) + at annotation.Foo.main(Foo.java:22) + Suppressed: java.lang.RuntimeException: Foo1 + at annotation.Foo.close(Foo.java:12) + at annotation.Foo.$closeResource(Foo.java:22) + at annotation.Foo.main(Foo.java:22) + Suppressed: java.lang.RuntimeException: Foo0 + at annotation.Foo.close(Foo.java:12) + at annotation.Foo.$closeResource(Foo.java:22) + at annotation.Foo.main(Foo.java:22) + +Process finished with exit code 1 +``` + +除了 try-with-resources 语法糖之外,Java 7 还支持在同一个 catch 代码块中捕获多种异常。实际实现非常简单,生成多个异常表条目即可。 + +```java +// 在同一 catch 代码块中捕获多种异常 +try { + ... +} catch (SomeException | OtherException e) { + ... +} +``` + #### 参考 -[JVM是如何处理异常的?](https://time.geekbang.org/column/article/12134) \ No newline at end of file +[JVM是如何处理异常的?](https://time.geekbang.org/column/article/12134) + +[try-with-resources 的理解](https://www.jianshu.com/p/08d03356ff8a) \ No newline at end of file diff --git a/images/Java/Exception.png b/images/Java/Exception.png new file mode 100644 index 0000000..a846268 Binary files /dev/null and b/images/Java/Exception.png differ diff --git a/images/Java/finally 执行流程.png b/images/Java/finally 执行流程.png new file mode 100644 index 0000000..ef8a859 Binary files /dev/null and b/images/Java/finally 执行流程.png differ