基于栈的虚拟机
Created|Updated
|Word Count:13|Reading Time:1mins|Post Views:
基于栈的虚拟机,可移植性更好。
Author: magicliang
Copyright Notice: All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Related Articles
2017-10-23
昂贵的异常
抛出问题 Joshua Bloch 在《Effective Java》的 Item 57 里明确地提到过,不要试图用 Exception 的跳转来代替正常的程序控制流。他列举了很多原因,但特别提到了抛出异常会使得整个程序运行变慢。抛出异常远比普通的 return , break 等操作对控制流、数据流的性能影响要大,它就只适合拿来作异常分支的控制语句,而不能拿来编写正常的逻辑。 Throwing exception is expensive. 这句话在 Java 的程序员世界里面已经成为老生常谈。却很少有人谈及,但到底抛出异常比正常的程序跳转返回慢在哪里,有多慢。“不要滥用异常”好像一个猴子定律,人们忘记了为什么不能这么做,却不明白为什么不能这么做。 这几天读了一位同事写的好文[《Java虚拟机是如何处理异常的》][2],深入地分析了 JVM 对异常跳转的处理过程: JVM...
2017-10-30
JVM 与编译优化
Java 的编译分期,至少可以分为两个阶段(有些情况下还有额外的第三种编译过程): 编译前端(前端编译):把 .java 变成 .class 文件的过程。也就是把源语言文件变成中间语言文件的过程。典型的例子有:javac、Eclipse 的 ECJ的工作过程。 编译后端(后端编译):由 JIT(Just In Time Compiler。我认为应该还要把 Interpreter包括在内)把中间语言(字节码)转换成二进制目标体系结构机器码的过程。典型的例子有,HotSpot 的 C1,C2编译器的工作过程。 AOT(Ahead Of Time) 编译器直接把源代码编译成转换成二进制目标体系结构机器码的过程。 早期(编译)优化 javac 自从1.3版本已经不再支持什么 -O 的优化了。所有的优化策略集中到后端编译里。这样没有经过 javac 编译的 JRuby、Jython程序,也可以享受到 JVM 的优化福利。 javac的编译过程,大致上是: 解析和填充符号表(Parse and...
2017-11-10
线程安全与锁优化
线程安全什么是线程安全“当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。” 相对的线程安全,可以分成五个等级: 线程安全的分类不可变不可变的数据,都是线程安全的。不可变的对象引用,加上所有field都是不可变的。如果有得选,尽量连方法都是final的。 绝对线程安全Vector不是线程安全的。它也会出现并发修改时 Out of Range 的异常(注意,不是 ConcurrentModification 的异常)。 相对线程安全需要保证对这个对象的单独操作是线程安全的,在调用的时候不需要加上额外的保障措施。对于特定顺序的连续操作,就需要额外的同步来保证调用的正确性了。 线程兼容可以通过特殊手段做到线程安全的普通类,绝大部分类都属于相对线程安全的。 线程对立线程对立,是不管调用端是否采取了同步措施,都无法在多线程环境中使用的代码。常见的线程对立的操作还有 suspend(),resume(),...
2017-11-03
JVM 的内存模型与线程
1.性能何处寻 计算机的CPU比起其他所有的设备,都快得多,所以怎样尽量复用 CPU 的时间片,是压榨计算机性能的目标。多核和并发,使得阿姆达尔定律大显神威,超越摩尔定律成为提升系统性能的金科玉律 - 现在单核计算能力已经无法垂直提升,要水平提升核数来提升整体性能。 2.缓存一致性问题(Cache Coherence) 软件缓存,不过是硬件缓存的模仿,真正的缓存,早已存在于计算机的多级存储体系结构中。JVM 里,我们可以认为每个处理器都会在主内存(Main Memory)之外有高速缓存作为工作内存(Working memory)。除此之外,处理器和 JVM 都可能出现指令重排(Instruction Reorder)的的情况。工作内存是线程 Save 和 Load 的主要场所,主内存则是他们沟通的场所。 3.JVM 的对象信息 Java Object 除了基本的内存轮廓以外,还有: Mark Word(对象的 Hash Code 的缓存值、GC标志、GC年龄、同步锁等信息)。 Klass...
2017-12-24
client 与 server
client 模式默认的jit编译器,c1。默认的gc:serial-serial old。需要更短的启动时间和初始堆大小,能做更保守的优化。默认-Xms是1M,-Xmx是64M。适合 GUI 程序。 server 模式默认的jit编译器,c2。默认的gc:ps-serial old即 PS MarkSweep(可以启用parallel old)。需要更长的启动时间和更大的堆大小,能够做更有深度的优化。默认-Xms是128M,-Xmx是1024M。适合长时间运转的程序。 64 位JVM在64位 JVM 上有个 -d64 的模式,实际上就是禁止client模式单独启动,只允许server模式或者混合编译模式启动的模式。
2018-09-10
OOM 调查使用到的工具
基础工具 top 与 htop。这两个东西比 free 好用。比较神奇的是,为什么线上还有装了 htop这样的非标准 top。字节跳动自己开源了一个 atop,可以细致地监控线程信息,也可以快速采集系统信息,是一个不错的监控工具。 pmap。这个东西是莫枢自己也用来 dump 详细的内存轮廓的地址,但可能需要使用他提到的一个 Serviceability Agent API 来读才读得懂。这个工具的输出可以看到各段内存的起止,但不经帮助,很难读出各个子线程的栈来。这个命令在非 root/sudo 权限下看到的是 jvm 启动参数,在 root/sudo 权限下看到的是内存轮廓,这时候就需要 Serviceability Agent API 了。 smem。这个东西对内存的 RSS/PSS/USS 分析得很好。但并不能帮助我们直接获知我们最期待的栈内存轮廓,比如当前 JVM 的 stack 到底是怎么分布的,占了多少内存?而且更重要是,线上机器没有这个工具。 直接 cat /proc/pid/smaps...
Announcement
人生只是,守株待兔
Recent Posts