I'm completely riddled with the following stacktrace... Looks like it is caused by the String
instance which has null
char array internally. Putting aside reflection, is there any "legal" way to get such String
instance in java?
Caused by: java.lang.NullPointerException: null
at java.lang.String.length(String.java:611) ~[na:1.8.0_31]
at org.apache.commons.lang.StringUtils.isEmpty(StringUtils.java:195) ~[commons-lang-2.6.jar:2.6]
If by legal you mean by using the constructors and methods exposed by the String
API, then, no, it is not possible to reproduce such an exception.
There are ways to instantiate classes that will skip constructors and initializers. sun.misc.Unsafe
provides such a utility, allocateInstance
.
public static void main(String[] args) throws Exception {
String string = (String) getUnsafe().allocateInstance(String.class);
System.out.println(string.length());
}
@SuppressWarnings("restriction")
private static Unsafe getUnsafe() {
try {
Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
singleoneInstanceField.setAccessible(true);
return (Unsafe) singleoneInstanceField.get(null);
} catch (Exception e) {
}
return null;
}
In this case, the value
field of String
will remain null
and the NullPointerException
will occur when invoking length()
.
Similarly, some proxying libraries that use byte code manipulation can omit an invocation to super()
when creating proxy subclasses, effectively skipping initialization. Here's a related question where mocking failed to properly initialize an ArrayList
's backing array.
Also see for reports of an npe on the same line in String.
- NullPointerException from within String is confusing
- java Strings odd behavior with collator
- https://twitter.com/s1m0nw/status/829728992907448326
There's a String(char[] value, boolean shared)
package protected constructor that does not do a null check.
My guess that this is used in combination with String intern, so not called directly by your code.
One hypothetical scenario here could be multithreading in combination with String intern. The value field in String is final but not volatile. This may lead to weird issues early in it's lifecycle.