《java performance》读书笔记之jvm runtime

5 篇文章 0 订阅
4 篇文章 0 订阅

vm runtime的主要功能:命令行参数解析、虚拟机生命周期维护、类加载、字节码解释、异常处理、同步、线程管理、jni、fatal error处理、c heap管理。

命令行解析:
NA

虚拟机生命周期:
NA

类加载:
NA

字节码解析(interpreter):
The template table generated in memory can be viewed using what is called a HotSpot
“debug” VM and the nonproduct flag -XX:+PrintInterpreter.
使用这两个参数,就可以打开printInterpreter:-XX:+UnlockDiagnosticVMOptions  -XX:+PrintInterpreter,而不需要debug版本的vm
TemplateTable是一个byteCode和机器语言的map集合 
Class DataSharing 是在java5引进的致力于缩短虚拟机启动时间的机制。通过把一部分通用的java class文件映射到磁盘文件中,在启动的时候直接内存映射回虚拟机内存中,降低虚拟机启动时每次去加载这部分class文件的时间。

异常处理:
NA

同步(synchronization):
jvm中线程同步和锁
http://blog.csdn.net/chen77716/article/details/6618779
http://wenku.baidu.com/view/bafd15f57c1cfad6195fa71c.html
同步中有几个关键词:偏向锁、快速路径、慢速路径
偏向锁是在无竞争的场景下完全消除同步,比如单线程访问带同步的资源或者方法。在jvm中,偏向锁是默认打开的,可以用-XX:-UseBiasedLocking 参数把偏向锁去掉。
偏向锁偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。
如果在运行过程中遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。(偏向锁只能在单线程下起作用)
轻量级锁和偏向锁:
monitorenter于monitorexit这两个控制多线程同步的字节码是jvm依赖操作系统互斥来实现的,互斥是一种会导致线程挂起,并在较短时间内又需要重新调度回原线程的,较为消耗资源的操作。
为了优化Lock机制,从java6开始引入了轻量级锁的概念。Lightweight Locking本意是为了减少多线程进入互斥的几率,不是要替代互斥,它利用了CPU原语CAS,尝试在进入互斥前进行补救,从而避免使用互斥,减少资源消耗。

java中的对锁的优化从重量级锁到轻量级锁,此外还增加了偏向锁和自旋锁(为降低上下文切换的目的,在进入阻塞队列前自旋一会,暂用cpu时间,在这个时间完成后,等待的锁可能已经完成,就可以直接获取锁,就不需要上下文切换了)来降低使用锁的代价。

线程管理(thread management):
线程状态:MONITOR_WAIT---竞争锁的情况线程等待获取一个锁
    CONDVAR_WAIT---线程等待虚拟机内部的条件变量
    OBJECT_WAIT----线程条用了wait()方法

VM operations and safepoints
safepoints即为安全点,是vm在需要做一些操作的时候把运行的线程进入一个安全点的状态,这样才能做一些安全操作,最熟悉的安全点操作是FGC的支持,比如FGC时候的stop-the-world阶段。
另外一些safepoint比如:偏向锁撤销,即偏向锁在出现多线程竞争的时候,退回到轻量级锁、线程dump、线程挂起和暂停
线程会询问虚拟机是否要在safepoint暂停的场景是:线程状态切换、即时编译后的代码在一个循环阶段从一个方法返回或者特定的阶段。
http://hllvm.group.iteye.com/group/topic/28939:
Threads executing interpreted code do not usually ask whether they should block for a safepoint. Instead the safepoint is requested when the interpreter switches to a different dispatch table.
Once a safepoint has been requested, the VMThread must wait until all threads are known to be in a safepoint-safe state before proceeding to execute a VM operation.
翻译:一旦需要进入safepoint,VMThread会等到所有线程都进入安全点,即停止状态才进行VM级别的操作。
During a safepoint the Threads_lock is used to block any threads that are running. The VMThread releases the Threads_lock after the VM operation has been performed.
翻译:安全点期间,使用Threads_lock来让所有线程都block住,最后当VMThread执行完vm操作时释放Threads_lock让其余线程继续执行。


C++ Heap management:
A set of C++ classes derived from a base class called Arena is used to manage the HotSpot VM C++ heap operations.
翻译:一系列Arena的子类会执行管理C++ 堆管理的操作。
The Arena base class and its subclasses provide a rapid C/C++ allocation layer that sits on top of the C/C++ malloc/free memory management routines.
翻译:这些Arena的子类基于C++的malloc/free内存管理这条路径提供了快速的内存分配层。
每个Arena从三个主要的ChunkPools(Memory Blocks Pools)中分配Memory Block(内存块)。
每个ChunkPool为不同的分配大小的请求来分配内存块。比如,一个需要1K内存块的请求由small Chunkpools来分配,10k是medium ChunkPool。这样做是为了尽可能得避免内存碎片的浪费。
Arena方式比直接使用C/C++的malloc/free管理内存路径来分配内存拥有更好的性能,直接使用malloc/free的操作可能需要OS层级的锁,这有可能降低可扩展性并影响性能。
Arena是一些缓存了一定数量内存空间的ThreadLocal对象。由于不需要共享全局锁,这就使得快速路径的分配成为可能。
Arena还用于ThreadLocal的资源和句柄管理。client和server模式的JIT compilers都使用Arena。

JNI:
JAVA Native Interface 是一个本地编程接口,通过它可以让运行在java虚拟机内部的代码和其他诸如C、C++等语言的类库以应用进行交互。
程序员可以使用JNI来编写本地方法来处理一些纯java不能满足需求的情况。
JNI本地方法可以用来创建、检查和更新java对象,调用java方法,捕获和抛出异常,加载类、获取类型信息,进行运行时类型检查等。
JNI结合Invocation API还可以把本地程序嵌入到java虚拟机当中,这样程序员可以很方便得在自己的本地程序中加入java的特性。
但是使用JNI,可能会导致java的两个特性的丢失。一是跨平台的特性:“一次编译,随处运行”的允诺可能会出现问题。
二是java语言是类型安全的,但C/C++这类语言却不是,所以java开发组在使用JNI进行应用开发时需要格外注意类型安全的检查和确认。
Hotspot VM提供了一个命令行选项,-Xcheck:jni来帮助排查使用JNI导致的问题。这个选项开启之后,jvm会使用另外一套便于debug的JNI接口,这套接口在处理JNI调用时会对一致性和类型安全做更严格的检查。
HotSpot VM需要对当前正运行在本地方法中的线程格外留意,比如:jvmGC是需要让所有线程都进入safepoint,而对于一个正运行在本地代码中的线程,这个线程可以等到把本地代码执行完毕要退回到java代码时再暂停
进入safepoint。

VM FATAL ERROR:
jvm中比较普遍的vm fatal error是OutOfMemoryError和linux | solaris 平台上的 segmentation fault,也即windows平台上的 access violation error。
当这些错误发生的时候,有时候需要去改动应用程序代码,有时候需要改动的是jvm自身(配置等)。
每当这些错误发生导致jvm crash,jvm都会dump一份名为 hs_err_pid<pid>.log的日志,使用-XX:ErrorFile命令行参数可以设置这个文件的地址。OutOfMemoryError也会触发这个文件的生成。日志文件中还会包含crash当时的
内存映射图。
一个对于分析jvm crash很有用的功能是:设置-XX:OnError=cmd1 args...;com2 ... .,OnError参数告诉jvm可以在jvm crash时执行指定的命令。对于不支持-XX:OnError参数的虚拟机来讲,另外一个jvm参数:
-XX:+ShowMessageBoxOnError,这个参数让jvm在即将要crash的时候显示一个jvm即将要crash的对话框,这个时候可以把jvm hold在这里,并在jvm退出之前attach一个debuger。
jvm内部使用一个叫做VMError的类来dump hs_err_pid的日志文件。jvm的内部组件之间使用信号来进行通信,jvm的fatal error处理器,即这个VMError类在接收到一个无法识别的信号时被调用,fatal error的来源可能是JNI的代码、操作系统层面的类库、jre类库以及虚拟机本身。
对于OutOfMemoryError,虚拟机参数-XX:+HeapDumpOnOutOfMemoryError可以用来指定在发生OutOfMemoryError错误时dump一份内存,-XX:HeapDumpPath=<pathname>这个参数可以用来指定dump出来的文件的放置地点。
对于死锁问题,可以使用dump线程堆栈的方式来排查,在windows系统,使用Ctrl + Break 可以让jvm dump出一份线程堆栈,在linux和solaris ,给jvm 进程发送一个SIGQUIT信号也可以做到同样的事情。此外,从java 6开始,
jconsole工具中也内置了死锁检查的功能。此外,使用btrace等工具也可以用来排查死锁问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值