我正在尝试调试Hadoop中的性能问题,其中一部分是我几次从不同的hadoop构建中捕获jstack,并在不同的Java版本上运行。当我的性能问题显现时,我得到了一个可运行线程的jstack,如下所示:
"DataXceiver for client DFSClient_NONMAPREDUCE_-619388227_1 at /x.x.x.x:35518 [Sending block BP-1509854702-x.x.x.x-1392815592442:blk_3738093208_1102227094469]" daemon prio=10 tid=0x00007f1a683cf800 nid=0xb61d1 runnable [0x00007f1a36060000]
java.lang.Thread.State: RUNNABLE
at org.apache.hadoop.hdfs.util.FoldedTreeSet.get(FoldedTreeSet.java:449)
at org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.ReplicaMap.get(ReplicaMap.java:111)
- locked <0x0000000751682590> (a org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl)
at org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.ReplicaMap.get(ReplicaMap.java:89)
at org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl.getVolume(FsDatasetImpl.java:177)
- locked <0x0000000751682590> (a org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl)
at org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl.getVolume(FsDatasetImpl.java:127)
at org.apache.hadoop.hdfs.server.datanode.BlockSender.<init>(BlockSender.java:283)
at org.apache.hadoop.hdfs.server.datanode.DataXceiver.readBlock(DataXceiver.java:537)
at org.apache.hadoop.hdfs.protocol.datatransfer.Receiver.opReadBlock(Receiver.java:148)
at org.apache.hadoop.hdfs.protocol.datatransfer.Receiver.processOp(Receiver.java:103)
at org.apache.hadoop.hdfs.server.datanode.DataXceiver.run(DataXceiver.java:246)
at java.lang.Thread.run(Thread.java:744)
如果我检查堆栈顶部的源代码行449是此方法的一部分,并且始终位于突出显示的右花括号中。每次发生此问题时,堆栈跟踪都是相同的,而我在Java 7和Java 8上已经看到过。
public E get(Object obj, Comparator<?> cmp) {
Objects.requireNonNull(obj);
Node<E> node = root;
while (node != null) {
E[] entries = node.entries;
int leftIndex = node.leftIndex;
int result = compare(obj, entries[leftIndex], cmp);
if (result < 0) {
node = node.left;
} else if (result == 0) {
return entries[leftIndex];
} else {
int rightIndex = node.rightIndex;
if (leftIndex != rightIndex) {
result = compare(obj, entries[rightIndex], cmp);
}
if (result == 0) {
return entries[rightIndex];
} else if (result > 0) {
node = node.right;
} else {
int low = leftIndex + 1;
int high = rightIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
result = compare(obj, entries[mid], cmp);
if (result > 0) {
low = mid + 1;
} else if (result < 0) {
high = mid - 1;
} else {
return entries[mid];
}
}
return null;
}
}
} // *** This is line 449 which the jstack always has at the top of the stack.
return null;
}
我有同一行的其他jstack示例,其中行号看起来正确,因此,我认为我看的不是该类的错误版本。肯定已使用与运行进程的同一用户相同的Java主页中的jstack命令捕获了jstack。关于样本的其他所有内容看起来都是正确的。
任何人都可以提供任何原因说明为什么jstack总是将右括号显示为可运行行吗?在查看许多jstacks输出之前,我从未见过。
更新
调查这是由编译和源代码中的不匹配引起的建议,我从与上述相同的过程中找到了另一个堆栈样本:
"Thread-41" daemon prio=10 tid=0x0000000003c39000 nid=0x1c6fe1 runnable [0x00007f1a4b7b8000]
java.lang.Thread.State: RUNNABLE
at org.apache.hadoop.hdfs.util.FoldedTreeSet.removeAndGet(FoldedTreeSet.java:879)
at org.apache.hadoop.hdfs.util.FoldedTreeSet.removeAndGet(FoldedTreeSet.java:892)
at org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.ReplicaMap.remove(ReplicaMap.java:162)
- locked <0x0000000751682590> (a org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl)
at org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl.invalidate(FsDatasetImpl.java:2021)
- locked <0x0000000751682590> (a org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl)
at org.apache.hadoop.hdfs.server.datanode.BPOfferService.processCommandFromActive(BPOfferService.java:686)
at org.apache.hadoop.hdfs.server.datanode.BPOfferService.processCommandFromActor(BPOfferService.java:632)
at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.processCommand(BPServiceActor.java:729)
at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.offerService(BPServiceActor.java:539)
at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.run(BPServiceActor.java:695)
at java.lang.Thread.run(Thread.java:744)
这是同一类中的不同方法,但是removeAndGet方法中的代码与get中的代码非常相似。以下是相关的代码段:
public E removeAndGet(Object obj) {
return removeAndGet(obj, comparator); // *** This is 892, this is correct as per the stack trace above
}
public E removeAndGet(Object obj, Comparator<?> cmp) {
Objects.requireNonNull(obj);
if (!isEmpty()) {
Node<E> node = root;
while (node != null) {
E[] entries = node.entries;
int leftIndex = node.leftIndex;
int result = compare(obj, entries[leftIndex], cmp);
if (result < 0) {
node = node.left;
} else if (result == 0) {
return removeElementLeft(node);
} else {
int rightIndex = node.rightIndex;
if (leftIndex != rightIndex) {
result = compare(obj, entries[rightIndex], cmp);
}
if (result == 0) {
return removeElementRight(node);
} else if (result > 0) {
node = node.right;
} else {
int low = leftIndex + 1, high = rightIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
result = compare(obj, entries[mid], cmp);
if (result > 0) {
low = mid + 1;
} else if (result == 0) {
return removeElementAt(node, mid);
} else {
high = mid - 1;
}
}
return null;
}
}
} // **** This is 879 - again the same as the get method
}
return null;
}
源文件中稍后的代码似乎正确,但这奇怪地再次指向大括号。
最佳答案
在您的源代码和编译的类不同的情况下,有99%会发生这种情况。即编译的类是从其他来源(较新或较旧的版本)编译的。可能需要反编译您的类(从.class生成.java),看看是否有帮助
关于java - Java jstack示例指向右括号而不是代码行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59823880/