什么是;“消除”;在Java堆栈跟踪中是什么意思?
我正在查看Java应用程序的一个线程转储,并注意到有时我看到的不是“锁定”,而是关键字“已消除”,如下所示:什么是;“消除”;在Java堆栈跟踪中是什么意思?,java,Java,我正在查看Java应用程序的一个线程转储,并注意到有时我看到的不是“锁定”,而是关键字“已消除”,如下所示: "Worker [4]" prio=10 tid=0x00007fb1262d8800 nid=0x89a0 in Object.wait() [0x00007fb15b147000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method)
"Worker [4]" prio=10 tid=0x00007fb1262d8800 nid=0x89a0 in Object.wait() [0x00007fb15b147000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
at com.myapp.common.util.WaitableQueue.getAll(WaitableQueue.java:152)
- eliminated <0x00000004d0d28e18> (a com.myapp.common.util.balq.SingleQueueQController$_WorkerQueue)
at com.myapp.common.util.balq.SingleQueueQController$_WorkerQueue.getAll(SingleQueueQController.java:3527)
- locked <0x00000004d0d28e18> (a com.myapp.common.util.balq.SingleQueueQController$_WorkerQueue)
at com.myapp.common.util.AbstractWorker.read(AbstractWorker.java:678)
at com.myapp.common.util.AbstractWorker.runBulk(AbstractWorker.java:541)
at com.myapp.common.util.AbstractWorker.run(AbstractWorker.java:343)
“Worker[4]”prio=10 tid=0x00007fb1262d8800 nid=0x89a0在对象中。等待()[0x00007fb15b147000]
java.lang.Thread.State:正在等待(在对象监视器上)
在java.lang.Object.wait(本机方法)
等待(Object.java:503)
在com.myapp.common.util.WaitableQueue.getAll(WaitableQueue.java:152)上
-已消除(com.myapp.common.util.balq.SingleQueueQController$\u WorkerQueue)
位于com.myapp.common.util.balq.SingleQueueQController$\u WorkerQueue.getAll(SingleQueueQController.java:3527)
-锁定(com.myapp.common.util.balq.SingleQueueQController$\u WorkerQueue)
位于com.myapp.common.util.AbstractWorker.read(AbstractWorker.java:678)
位于com.myapp.common.util.AbstractWorker.runBulk(AbstractWorker.java:541)
位于com.myapp.common.util.AbstractWorker.run(AbstractWorker.java:343)
令人惊讶的是,我在谷歌上找不到与此相关的任何信息。“已锁定”和“已消除”关键字之间有什么区别?它表示字节码中已删除的冗余锁。 我总是觉得源代码是这样开始的好地方。openJDK对hotspot/src/share/vm/opto/callnode.cpp的评论如下:
// Redundant lock elimination
//
// There are various patterns of locking where we release and
// immediately reacquire a lock in a piece of code where no operations
// occur in between that would be observable. In those cases we can
// skip releasing and reacquiring the lock without violating any
// fairness requirements. Doing this around a loop could cause a lock
// to be held for a very long time so we concentrate on non-looping
// control flow. We also require that the operations are fully
// redundant meaning that we don't introduce new lock operations on
// some paths so to be able to eliminate it on others ala PRE. This
// would probably require some more extensive graph manipulation to
// guarantee that the memory edges were all handled correctly.
//
// Assuming p is a simple predicate which can't trap in any way and s
// is a synchronized method consider this code:
//
// s();
// if (p)
// s();
// else
// s();
// s();
//
// 1. The unlocks of the first call to s can be eliminated if the
// locks inside the then and else branches are eliminated.
//
// 2. The unlocks of the then and else branches can be eliminated if
// the lock of the final call to s is eliminated.
//
// Either of these cases subsumes the simple case of sequential control flow
因此,从上面看来(至少在openJDK中),消除意味着JVM通过一组或多组释放/获取指令来维护锁
查看hotspot/src/share/vm/runtime/vframe.cpp中的javaVFrame::print\u lock\u info\u on()
显示检查和输出发生的位置:
// Print out all monitors that we have locked or are trying to lock
GrowableArray<MonitorInfo*>* mons = monitors();
if (!mons->is_empty()) {
bool found_first_monitor = false;
for (int index = (mons->length()-1); index >= 0; index--) {
MonitorInfo* monitor = mons->at(index);
if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code
if (monitor->owner_is_scalar_replaced()) {
Klass* k = Klass::cast(monitor->owner_klass());
st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name());
} else {
oop obj = monitor->owner();
if (obj != NULL) {
print_locked_object_class_name(st, obj, "eliminated");
}
}
continue;
//打印出我们已锁定或试图锁定的所有监视器
GrowtableArray*mons=monitors();
如果(!mons->为空(){
bool found\u first\u monitor=false;
对于(int index=(mons->length()-1);index>=0;index--){
MonitorInfo*monitor=mons->at(索引);
if(monitor->employed()&&is_compiled_frame()){//在编译代码中消除
如果(监视器->所有者被替换()){
Klass*k=Klass::cast(monitor->owner_Klass());
st->print(“\t-已消除(a%s)”,k->external_name());
}否则{
oop obj=监视器->所有者();
如果(obj!=NULL){
打印锁定对象类名称(st,obj,“已消除”);
}
}
继续;
进一步的评论,包括上面的评论,也暗指用NOP替换锁定和解锁说明
我阅读了德克提到的关于锁粗化而非省略的文档:
另一个可用于降低锁定成本的优化是锁粗化。锁粗化是合并使用相同锁对象的相邻同步块的过程。如果编译器无法使用锁省略消除锁定,则可以使用锁粗化来减少开销
但是说实话,差别是很微妙的,最终的效果几乎是一样的,你可以消除不必要的锁和解锁。可能指的是。谢谢你链接到这篇伟大的文章!它肯定会符合我所看到的。@德克你可以考虑回答这个问题。所以它没有显示出没有答案。s链接也可能有帮助: