
本想用一篇日志记录下在 Docker 容器中使用 Java 调用 C++ 动态库时,当 C++ Crash 时如何自动生成 core dump, 不想分成了至少三篇来完成这一研究。 可以回顾一下前两篇日志
本文是基于第二篇进一步推进,继续探索如何在 Docker 容器中 Java 调用 C++ 动态库时的 core dump 如何生成。首先测试的平台依然是 AWS EC2 实例, OS 为 Amazon Linux 2023, Docker 版本为 25.0.14。为叙事方便,本文所用代码与上篇一样,但还是重复一遍,省却了连接跳转。
Read More
在 Java 应用程序通过 JNA 调用 C++ 动态库时,C++ 代码运行在与 Java 同一进程中,当 C++ 代码 Crash 的时候,将会导致整个 Java 应用程序崩溃。 对于一个 Web 应用,这不是我们期望的结果,由于某一个请求输入的数据导致 C++ 代码崩溃了当前 Java 进程,从而造成该 Web 服务已接受到的所有请求全部失败, 这是非常糟糕的用户体验。如果是 Java 代码本身的异常我们可用 try/catch 进行保护,影响只限制在当前请求。如果是 C++ 代码崩溃的话,Java 应用程序无法捕获到这个异常,以致于整个 Java 应用程序崩溃,甚至发生这种情况时连 hs_err.log 文件都来不及生成,更别说生成 HeapDump, 或 CoreDump 了。
如果是用原始 JNI 的方式来调用动态库,我们还能在 JNI 相关的 C++ 代码中捕获到异常,并抛给 Java 去处理。而用 JNA, 我们贪图了它的方便, 比如一个 Java 进程中同时加载同一接口的不同动态库版本(JNI 要同样的实现必须用自定义的 ClassLoader),但在 C++ 代码崩溃时, Java 就显得无能为力了, 只能跟随着立即死亡, 并且在控制台下找不到关于 C++ 因何失败的线索。比如 C++ 中内存被多次释放,或地址越界访问破坏了内存数据等。
Read More
本文初衷是为了解决 Java 应用程序通过 JNA 调用 C++ 动态库时,C++ 代码运行崩溃导致整个 Java 应用程序崩溃而进行的研究。从一个 C++ 调用 C++ 写的动态库起步,记录它在什么情况下产生 core dump 文件,如何分析 core dump 文件等过程。可惜篇幅无法控制,不足以再加入 Java->JNA->C++ 动态库内容了,所以不得不单列此篇,并更名为 'C++ 调用 C++ 动态库时问题诊断'. 关于 Java JNA 到 C++ 的问题诊断只能另立一篇了。
下面我们来用 JNA 的方式来调用 C++ 动态库,演示当 C++ 代码崩溃时会发生什么,并试图找到好的诊断办法。以下演示在 Linux 下进行, 并且 Linux 发行版是 Amazon Linux 2023.
Read More
Java 24 也是一个过渡版本, 还是到下面两个链接中找相应的更新
IntelliJ IDEA 对 Java 22 Language level 描述是
- 23 - Markdown document comments
- 22(Preview) - Primitive types in patterns, implicitly declared classes, etc.
把上面第二个链接中的特性列出来
本文对上面用红点标记的特性重点关注
Read More
Java 22 是一个过渡版本, 还是到下面两个链接中找相应的更新
IntelliJ IDEA 对 Java 22 Language level 描述是
- 22 - Unnamed variables and patterns
- 22(Preview) - Statements before super(), string templates (2nd preview), etc.
把上面第二个链接中的特性列出来
本文对上面用红点标记的特性重点关注
Read More
迁移完所有的 WordPress 日志到 Hugo 之后, 终于有时间真正继承学习相关的新技术. Java 21 是于 2023 年 9 月份释放出来的 LTS 版本, 目前主要在用该版. Java 25 LTS 版本已发布, 按正常节奏应该要切换到该版本.
随着 AI 在编程界的花式表演, 所宣传的似乎就是要扑灭他人的学习热情, 编程方面越小白越好, 只要能写好小作文就行了. AI 当然还是要用, 但我对以往多少年传统的学习方式并不感到白花了心血. 告诉 AI 的一个课题 AI 确实能写出一篇漂亮, 规整的博客文章, 但其中有没有胡说八道, 只有试了才知道, 即使生成的文章无误, 也必须实践一遍才有更多更深的斩获.
如果没有相关的技术储备, 每次与 AI 互动的时候都要告诉它尽量用 Java 21 新特性, 因为新引入的特性基本能实现得更简洁, 高效, 估计 AI 才不那么在乎这些, 写出适于人阅读的代码恐怕不是 AI 的首要关注.
还是老办法, 关于 Java 某一版本新特性从两个链接出发
Read More
篇首说明: 本文十分冗长, 语言组织混乱, 如果觉得 TLDR, 就直接跳到 关于虚拟线程的总结 部分看要点, 若对总结上中的某些要素点仍有兴趣的话请倒查本文中其他部分的内容. 个人对 Java 虚拟线程的主动研究是为了在项目中更有效的使用它.
关于线程的概要
Java 21 于两年前 2023 年 9 月份放出,它是一个 LTS(long term support) 版本,个人基本就是把 LTS 当作能在正式项目中使用的版本。 Java 21 有几个增进编程体验的特性,像 Sequenced Collections, Record Patterns, 和 Pattern Matching for switch, 而对于性能改进的, 也是 Java 21 最具代表的特性无疑就是 Virtual Threads -- 虚拟线程。本文单列出它来,着重感受一下虚拟线程是什么,以及我们应该如何使用它。
其实在之前的 Java 19, 20 新特性学习 就有一定的笔墨介绍了于 Java 19 引入, Java 20 中尚处于第二次预览的虚拟线程。于其中大致体验了在一台 36 G 物理内存,默认堆内存为 9 G 的情况下, 创建 9000 个线程没问题,但要创建 10000 个线程就 OutOfMemoryError 了。而相同的环境下创建一百万个虚拟线程都没问题,没在继续往下试探了。
其实这种比较是没有意义的, Java 线程对应到平台线程的, 每个线程要至少实实在在的 2M 栈空间, 而一百万个虚拟线程相当于是创建了一百万个 Java 对象而已, 更像是相应数量的 Task, 实际运行时才由载体线程去调度执行 - (注: 后面所提到的载体线程和平台线程是同一个概念).
重新回顾一下何谓虚拟线程,Java 的虚拟线程实现是来自于 Project Loom 项目。与此相关的概念有线程,协程,以及纤程(Fiber),而虚拟线程对应的应该是纤程。
- 线程是操作系统最小的调度单位,每个线程有独立较大的栈空间(比如 2M),内核调度,切换开销大,可有效使用 CPU 多核
- 协程在单个线程内执行,共享线程栈空间或独立小空间,用户态调度,切换开销极小,但无法使用多核
- 纤程,介于线程与协程之间,很小的独立栈,用户态调度,切换开销较小。结合线程池,纤程可在线程间转移,这时岂不是要经内核态调度吗?
之所以把 Java 19 与 20 放一块是因为这两个版本都没有一个算得上正式的特性。都是些预览的,孵化中的,唯有一个支持 Linux 下 RISC-V 指令集与我们基本无关。所以 Java 19 和 Java 20 纯粹的过度版本,根本不该被正式项目采用,在 IntelliJ IDEA 中也是标它们为 No new language features。在我们的实践中正式项目只用 LTS 版。
还是分别从 https://openjdk.org/projects/jdk/19/ 和 https://openjdk.org/projects/jdk/20/ 抓关注点
从上面可以挑几个稍加了解,详细的介绍应该在学习 Java 21 时。它们是 Read MoreJava 19 新特性 Java 20 新特性
有了 AI 是不是就用不着了解语言特性本身呢?用 Vibe Coding 难道就无所不能呢?如果是的话那些找工作的也就无需刷 LeetCode 了。试想 Vibe Coding 产生了成堆的代码,即使创建了 Pull Request, 也不是给人 Review 的,也只能由 AI 来 Review, 到头来就是 AI 与 AI 自己玩,有 Bug 也只有 AI 看得懂。以后的屎山代码是一车一车的来。
除了从 JDK 官方每个版本的 What's New in JDK 18 - New Features and Enhancements, 还可以看 OpenJDK JDK 18 列出的更简明的新特性。自 JDK 10 之后,每一版的新特性由链接 https://openjdk.org/projects/jdk/<version>/ 查看,如 JDK 10 新特性链接为 https://openjdk.org/projects/jdk/10/。
在 https://openjdk.org/projects/jdk/18/ 列出了 JDK 18 如下新特性- 400: UTF-8 by Default
- 408: Simple Web Server
- 413: Code Snippets in Java API Documentation
- 416: Reimplement Core Reflection with Method Handles
- 417: Vector API (Third Incubator)
- 418: Internet-Address Resolution SPI
- 419: Foreign Function & Memory API (Second Incubator)
- 420: Pattern Matching for switch (Second Preview)
- 421: Deprecate Finalization for Removal
找几个有代表性的着重加了学习 Read More
昨天单列了 Java 17 新特性之密封类型, 继续刷 What's New in JDK 17 - New Features and Enhancements.switch 模式匹配(预览)
在 Java 21 才正式放出,主动就是原来的 switch...case 语句可以写成表达式的方式,有返回值, 无需每个分支的 break, 并增加模式匹配功能,比如匹配类型,带约束子条件,匹配 record 的字段值等,这里不展开说明,待到详细了解 Java 21 新特性时再深入研究。新的 macOS 渲染管道
英文是 New macOS Rendering Pipeline, 主要是 Swing API 如果配置系统属性-Dsun.java2d.meta=true就可以用 Apple Metal 替代 OpenGL 加速渲染界面,很少写 Java Swing 桌面应用的略过。新的 API 可访问大图标
同样是在对 Swing 的改进,可用 FileSystemView 加载解析度的图标 Read More