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.