我们在申请中看到了非常奇怪的行为。 我们有这个简单的代码:
public boolean isPrimitiveType()
{
for (int i=0;i<m_primitiveTypes.length; i++)
{
if (m_type.compareTo(m_primitiveTypes[i]) == 0)
{
if (log.isDebugEnabled())
{
log.fatal("isPrimitiveType() - type="+m_type+", checking with " + m_primitiveTypes[i] + " iteration " + i + " result " + m_type.compareTo(m_primitiveTypes[i]) + " array "
+ Arrays.toString(m_primitiveTypes) + " with equals " + m_type.equals(m_primitiveTypes[i]));
}
return true;
}
}
return false;
}
数组m_primitiveTypes非常简单:[java.lang.String,boolean,int,long,float,short]
类型:m_primitiveTypes是String [],m_type是String。
我们看到的是,经过一段时间(对该方法的多次调用),我们看到错误的结果 - 我们将此方法称为“m_type”等于“java.util.Vector”,但它返回true,尽管它应该返回假。 上面的致命日志显示了这一行:
2015-08-26 02:18:32,665 [WSM_REQUEST_SERVICE(1)(pid:14529)] FATAL com.intel.swiss.sws.mechanism.pxml.PXMLTag - isPrimitiveType() - type=java.util.Vector, checking with java.lang.String iteration 0 result 0 array [java.lang.String, boolean, int, long, float, short] with equals false
这很奇怪 - 似乎“java.util.Vector”.compareTo(“java.util.String”)返回0而“java.util.Vector”.equals(“java.util.String”)返回假的。
也许compareTo不是线程安全的?正如我所说的那样,只有在经过一段时间后才会发生这种情况。即使在它发生之后,在某些情况下它也能按预期工作。
对这个谜团有什么猜测?
由于
更新:
我创建了这个隔离代码的类,但仍然会重现问题:
import java.util.Random;
public class PXMLTag
{
public String m_type;
public static Random m_random = new Random();
private static String[] m_primitiveTypes = {"java.lang.String",
"boolean",
"int",
"long",
"float",
"short"};
private static String[] m_allTypes = {"java.lang.String",
"boolean",
"int",
"long",
"float",
"java.util.Vector",
"java.util.Map",
"short"};
public PXMLTag()
{
super();
}
public boolean isPrimitiveType()
{
for (int i=0;i<m_primitiveTypes.length; i++)
{
String type = m_type;
String primitiveType = m_primitiveTypes[i];
if (type.compareTo(primitiveType) == 0)
{
return true;
}
}
return false;
}
public static void main(String[] args)
{
int threads = 1;
if (args.length == 1)
{
threads = Integer.parseInt(args[0]);
}
for (int i=0 ; i<threads ; i++)
{
Thread t = createThread();
t.start();
}
}
private static Thread createThread()
{
return new Thread(new Runnable(){
@Override
public void run()
{
while (true)
{
PXMLTag tag = new PXMLTag();
tag.m_type = getRandomType();
if (tag.isPrimitiveType() && notReallyPrimitiveType(tag.m_type))
{
System.out.println(tag.m_type + " not really primitive!");
System.exit(0);
}
try
{
Thread.sleep(m_random.nextInt(100));
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private boolean notReallyPrimitiveType(String m_type)
{
return m_type.contains("Vector") || m_type.contains("Map");
}
private String getRandomType()
{
return m_allTypes[m_random.nextInt(m_allTypes.length)];
}});
}
}
当运行5个线程时,程序在22秒后停止(意思是 - 重现问题): 时间/usr/intel/pkgs/java/1.7.0.45-64/bin/java -jar /tmp/tag.jar 5 java.util.Vector不是很原始! 0.036u 0.012s 0:22.38 0.1%0 + 0k 0 + 128io 0pf + 0w
即使有一个线程,我也能够重现这个问题: 时间/usr/intel/pkgs/java/1.7.0.45-64/bin/java -jar /tmp/tag.jar 1 java.util.Vector不是很原始! 0.048u 0.012s 1:46.92 0.0%0 + 0k 0 + 128io 0pf + 0w
我发现的另外一件事 - 在有问题的机器上,有5个线程 - 程序总是在~21-22秒后停止,这是巧合吗?我怀疑某种JIT优化可能吗? 对此有何想法?
对Marco的回应:我已经添加了你想要的版画,这就是我得到的:
这个奇怪的案例
输入'java.util.Map'
currentPrimitiveType'java.lang.String'
他们是平等的?假
他们被比较9
m_type'java.util.Map'
m_primitiveType [i]'java.lang.String'
他们是平等的?假
他们被比较9
java.util.Map不是很原始!
所以比较结果是9但是打印在if子句中,只有在比较结果为0时输入!
更新2:
我发现非常有趣的事情 - 使用-Xint(禁用热点编译器)运行相同的问题不会重现该问题。