A licensee reported an issue related JIT(1.2.2_006) in solaris.
There happens SIGSEGV in their servlet and the core dump is gotten.
Although they has not sent any test program yet(needs a lot of time
to extract small portion from their real application) ,
they send their detail investigation as an alternatives.
They found out it happened somewhere in the following function,
getSignature().
------>
char *
getSignature (JITInfo *jit, unsigned name_type_index)
{
union cp_item_type *constant_pool = cbConstantPool(jit->thisClass);
unsigned type_index = constant_pool[name_type_index].i & 0xffff;
return constant_pool[type_index].cp;
}
<------
They look into the core file and come to know the below inconsistency.
The way to get signature depends on whether the constant pool entry
is resolved or not.
According to core dump file,
even though the result of the "if" statement,
if (CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, methodIndex)) {
seems to be "true",
the getSignature(), which should be called on the "false" case, looks
called instead of fieldsig().
----->
char *
getMethodSignature (JITInfo *jit, unsigned methodIndex)
{
union cp_item_type *constPool = cbConstantPool(jit->thisClass);
unsigned char *type_table = constPool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
(void)resolveCarefully(jit, methodIndex);
if (CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, methodIndex)) {
/* Get the signature from the methodblock */
struct methodblock *mb;
mb = constPool[methodIndex].mb;
return fieldsig(&mb->fb);
} else {
/* Get the signature indirectly from the CONSTANT_NameAndType item */
return getSignature(jit, constPool[methodIndex].i & 0xffff);
}
}
<----
They believe the following senario.
- When "if" statement is executed by a thread-A, its result is "false.
- Until the getSignature being called, another thread-B resolves the
constant pool entry.
- Although the constant pool entry is resolved, thread-A tries to launch
getSignature().
There happens inconsistency between real constant pool status and
the "false" status of "if" statement which thread-A tested.
They also look into the interpreter part.
--->
JNIEXPORT const char * JNICALL
JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass c, jint cp_index)
{
ClassClass *cb = (ClassClass *)DeRef(env, c);
union cp_item_type *cp = cbConstantPool(cb);
unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
switch(type_table[cp_index]) {
case CONSTANT_InterfaceMethodref:
case CONSTANT_Methodref: {
ExecEnv *ee = JNIEnv2EE(env);
LINKCLASS_LOCK(EE2SysThread(ee)); /*** CONSTANTPOOL IS LOCKED **/
/* Entry may have been resolved by another thread */
if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
unsigned index = cp[cp_index].i; /* value of Fieldref field */
unsigned key2 = index & 0xFFFF; /* index to NameAndType */
unsigned signature_index = cp[key2].i & 0xFFFF;
LINKCLASS_UNLOCK(EE2SysThread(ee));
return cp[signature_index].cp;
}
LINKCLASS_UNLOCK(EE2SysThread(ee));
/* FALL THROUGH */
}
case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
return cp[cp_index].mb->fb.signature;
default:
(*env)->FatalError(env, "JVM_GetCPMethodSignatureUTF: illegal constant"
);
return NULL; /* Keep lint happy */
}
}
<---
Just before the similar "if" statement, constant pool is locked in interpreter
mode.
So, they believe that JIT also should handle the constant pool exclusively
by using LOCK or other feature.
===============================================================================
There happens SIGSEGV in their servlet and the core dump is gotten.
Although they has not sent any test program yet(needs a lot of time
to extract small portion from their real application) ,
they send their detail investigation as an alternatives.
They found out it happened somewhere in the following function,
getSignature().
------>
char *
getSignature (JITInfo *jit, unsigned name_type_index)
{
union cp_item_type *constant_pool = cbConstantPool(jit->thisClass);
unsigned type_index = constant_pool[name_type_index].i & 0xffff;
return constant_pool[type_index].cp;
}
<------
They look into the core file and come to know the below inconsistency.
The way to get signature depends on whether the constant pool entry
is resolved or not.
According to core dump file,
even though the result of the "if" statement,
if (CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, methodIndex)) {
seems to be "true",
the getSignature(), which should be called on the "false" case, looks
called instead of fieldsig().
----->
char *
getMethodSignature (JITInfo *jit, unsigned methodIndex)
{
union cp_item_type *constPool = cbConstantPool(jit->thisClass);
unsigned char *type_table = constPool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
(void)resolveCarefully(jit, methodIndex);
if (CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, methodIndex)) {
/* Get the signature from the methodblock */
struct methodblock *mb;
mb = constPool[methodIndex].mb;
return fieldsig(&mb->fb);
} else {
/* Get the signature indirectly from the CONSTANT_NameAndType item */
return getSignature(jit, constPool[methodIndex].i & 0xffff);
}
}
<----
They believe the following senario.
- When "if" statement is executed by a thread-A, its result is "false.
- Until the getSignature being called, another thread-B resolves the
constant pool entry.
- Although the constant pool entry is resolved, thread-A tries to launch
getSignature().
There happens inconsistency between real constant pool status and
the "false" status of "if" statement which thread-A tested.
They also look into the interpreter part.
--->
JNIEXPORT const char * JNICALL
JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass c, jint cp_index)
{
ClassClass *cb = (ClassClass *)DeRef(env, c);
union cp_item_type *cp = cbConstantPool(cb);
unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
switch(type_table[cp_index]) {
case CONSTANT_InterfaceMethodref:
case CONSTANT_Methodref: {
ExecEnv *ee = JNIEnv2EE(env);
LINKCLASS_LOCK(EE2SysThread(ee)); /*** CONSTANTPOOL IS LOCKED **/
/* Entry may have been resolved by another thread */
if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
unsigned index = cp[cp_index].i; /* value of Fieldref field */
unsigned key2 = index & 0xFFFF; /* index to NameAndType */
unsigned signature_index = cp[key2].i & 0xFFFF;
LINKCLASS_UNLOCK(EE2SysThread(ee));
return cp[signature_index].cp;
}
LINKCLASS_UNLOCK(EE2SysThread(ee));
/* FALL THROUGH */
}
case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
return cp[cp_index].mb->fb.signature;
default:
(*env)->FatalError(env, "JVM_GetCPMethodSignatureUTF: illegal constant"
);
return NULL; /* Keep lint happy */
}
}
<---
Just before the similar "if" statement, constant pool is locked in interpreter
mode.
So, they believe that JIT also should handle the constant pool exclusively
by using LOCK or other feature.
===============================================================================
- relates to
-
JDK-4033703 Constant pool resolution by JIT compiler is not fully synchronized.
- Closed