java.lang.IllegalArgumentException: Comparison method violates its general contract!
[2017-05-18T11:22:20.626][DBG]io exception
at java.util.ComparableTimSort.mergeHi(Unknown Source)
at java.util.ComparableTimSort.mergeAt(Unknown Source)
at java.util.ComparableTimSort.mergeForceCollapse(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at com.vixtel.insight.xrobot.test.MP4Parser.showSizeToTimeStamp(TestScriptFlv.java:1400)
at com.vixtel.insight.xrobot.test.MP4Parser.handleMoov(TestScriptFlv.java:1182)
at com.vixtel.insight.xrobot.test.MP4Parser.parseVersion2nd(TestScriptFlv.java:1111)
at com.vixtel.insight.xrobot.test.TestScriptFlv.onReceive(TestScriptFlv.java:627)
at com.vixtel.insight.xrobot.test.TestScriptFlv$1.run(TestScriptFlv.java:457)
at java.lang.Thread.run(Unknown Source)
jdk 7的sort函数的实现变了,造成了这个问题。改一下系统设置,还是选择使用老版本的排序方法,在代码前面加上这么一句话:System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
if (this.beginSize == o.beginSize && this.endSize == o.endSize) {
return 0;
}else if (this.beginSize > o.beginSize) {
return 1;
} else {
return -1;
}
[1,2].compareTo([1,3]) = -1 => [1,2] < [1,3]
[1,3].compareTo([1,2]) = -1 => [1,3] < [1,2]
显然有问题,自相矛盾!!!
修改为:
public int compareTo(BeginToEnd o) {
if (this.beginSize > o.beginSize) {
return 1;
}else if(this.beginSize < o.beginSize) {
return -1;
}else{
if(this.endSize == o.endSize){
return 0;
}
else if(this.endSize > o.endSize) {
return -1;
}else {
return 1;
}
}
其他摘录:
根据他们的提示,我大概了解了compare方法需要返回 1,-1, 0即你的返回值要符合约定。
于是我又按照异常提示看了Collections的sort方法源码,如图:.......
继续跟踪Arrays类的sort方法:
看到这里我基本就豁然开朗了,因为抛异常的地方是在TimSort类里,说明实际走的是else分支,所以有了第一种解决方法,添加-Djava.util.Arrays.useLegacyMergeSort=true这个JVM参数,其实要真正解决这个问题,要符合规范的实现compare方法,因为他写的代码里没有考虑对象o1和对象o2为 Null的情况,即当o1与o2都为null时两者大小如何判定呢,当o1为null但o2不为null时两者大小又如何判定了呢,同理当o2为null
[2017-05-18T11:22:20.626][DBG]io exception
at java.util.ComparableTimSort.mergeHi(Unknown Source)
at java.util.ComparableTimSort.mergeAt(Unknown Source)
at java.util.ComparableTimSort.mergeForceCollapse(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at com.vixtel.insight.xrobot.test.MP4Parser.showSizeToTimeStamp(TestScriptFlv.java:1400)
at com.vixtel.insight.xrobot.test.MP4Parser.handleMoov(TestScriptFlv.java:1182)
at com.vixtel.insight.xrobot.test.MP4Parser.parseVersion2nd(TestScriptFlv.java:1111)
at com.vixtel.insight.xrobot.test.TestScriptFlv.onReceive(TestScriptFlv.java:627)
at com.vixtel.insight.xrobot.test.TestScriptFlv$1.run(TestScriptFlv.java:457)
at java.lang.Thread.run(Unknown Source)
jdk 7的sort函数的实现变了,造成了这个问题。改一下系统设置,还是选择使用老版本的排序方法,在代码前面加上这么一句话:System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
问题原因(百度知):产生该问题的原因是JDK1.6+要求所有比较器必须是可传递的(transitive),比如有A > B 和B > C,必须得保证有推出A > C(同理,对于=和<也需满足传递性)。而The ONE源码是基于JDK1.6的,JDK1.6没有该要求。
发散思维:(我的类BeginToEnd的确没有传递性 >> 对称性、传递性、反身性 >> 完备性)
public int compareTo(BeginToEnd o) {if (this.beginSize == o.beginSize && this.endSize == o.endSize) {
return 0;
}else if (this.beginSize > o.beginSize) {
return 1;
} else {
return -1;
}
[1,2].compareTo([1,3]) = -1 => [1,2] < [1,3]
[1,3].compareTo([1,2]) = -1 => [1,3] < [1,2]
显然有问题,自相矛盾!!!
修改为:
public int compareTo(BeginToEnd o) {
if (this.beginSize > o.beginSize) {
return 1;
}else if(this.beginSize < o.beginSize) {
return -1;
}else{
if(this.endSize == o.endSize){
return 0;
}
else if(this.endSize > o.endSize) {
return -1;
}else {
return 1;
}
}
其他摘录:
根据他们的提示,我大概了解了compare方法需要返回 1,-1, 0即你的返回值要符合约定。
于是我又按照异常提示看了Collections的sort方法源码,如图:.......
继续跟踪Arrays类的sort方法:
看到这里我基本就豁然开朗了,因为抛异常的地方是在TimSort类里,说明实际走的是else分支,所以有了第一种解决方法,添加-Djava.util.Arrays.useLegacyMergeSort=true这个JVM参数,其实要真正解决这个问题,要符合规范的实现compare方法,因为他写的代码里没有考虑对象o1和对象o2为 Null的情况,即当o1与o2都为null时两者大小如何判定呢,当o1为null但o2不为null时两者大小又如何判定了呢,同理当o2为null
但o1不为null时两者大小又如何判定呢又不得而知,或许你又会说,我这两个对象不可能为null,但那是你认为,JVM不知道,它只要求你的逻辑必须严谨,严格考虑各种情况下两者大小的判定原则。
(我的理解:对于comparable,可以不用考虑null,因为comparable在类中实现,必须有this不为null才会成功调用,所以需要保证不为null即可;对于comparator可以考虑作者的做法)