Bug #2524
closedAssertionError due to class loading order
100%
Description
Running this Java program
import net.sf.saxon.s9api.ItemType;
import net.sf.saxon.s9api.XdmAtomicValue;
public class ValidateNCName {
public static void main(String[] args) throws Exception {
// Class.forName("net.sf.saxon.type.BuiltInAtomicType");
// Class.forName("net.sf.saxon.type.StringConverter");
new XdmAtomicValue("x", ItemType.NCNAME);
System.out.println("success");
}
}
with JVM argument -verbose
shows that
-
net.sf.saxon.type.StringConverter
-
net.sf.saxon.type.BuiltInAtomicType
are loaded in this very order, which however causes their static initialization to behave in an unintended way, which subsequently causes an AssertionError:
This can be worked around by uncommenting the Class.forName
invocations.
Originally observed in a more complex setup with Saxon-EE 9.6.0.5, but also occurs with 9.7.0.1.
Updated by Michael Kay about 9 years ago
- Assignee set to Michael Kay
- Priority changed from Low to Normal
- Found in version changed from Saxon-EE 9.6.0.5 to 9.6
Very interesting - after all these years, Java still comes up with surprises.
As far as I can see, the root cause of the problem is that the two classes BuiltInAtomicType and StringConverter each have dependencies on each other in their static initializers, which means that one of the two is going to have its static initializers executed while the other is still uninitialized. Surprising that this hasn't come up before; and it's not immediately obvious what to do about it.
Updated by Michael Kay about 9 years ago
It seems to be possible to solve this by moving the static initializer of BuiltInAtomicType - the block that does
static {
STRING.stringConverter = StringConverter.STRING_TO_STRING;
etc
}
as static initializer of StringConverter instead. Very hard to know, though, whether this is a complete solution.
Perhaps a better solution would be to make the "constant" string converters into anonymous classes:
public final static BuiltInAtomicType HEX_BINARY =
makeAtomicType(StandardNames.XS_HEX_BINARY, ANY_ATOMIC, true,
new StringConverter() {
public ConversionResult convertString(/*@NotNull*/ CharSequence input) {
try {
return new HexBinaryValue(input);
} catch (XPathException e) {
return new ValidationFailure(e);
}
};
});
Updated by Michael Kay about 9 years ago
- Category set to Internals
- Status changed from New to Resolved
I have fixed this (this particular case, at least) for 9.6 and 9.7 by moving the static initializer block which sets the stringConverter of built-in types from the BuiltInAtomicType class to the StringConverter class.
Updated by O'Neil Delpratt about 9 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in version set to 9.6.0.8
Bug fix applied in the Saxon 9.6.0.8 maintenance release
Updated by O'Neil Delpratt about 9 years ago
- Applies to branch 9.6 added
- Fix Committed on Branch 9.6 added
- Fixed in Maintenance Release 9.6.0.8 added
Please register to edit this issue