Bug Java Exception when Zlib is running

Getting this error tonight : Unexpected error, debug log printed.
Script execution aborted (java.lang.NullPointerException): (zlib.ash, line 316)
Unexpected error, debug log printed.

Unexpected error, debug log printed.
class java.lang.NullPointerException: null
java.lang.NullPointerException
at java.base/java.io.ByteArrayInputStream.<init>(Unknown Source)
at net.sourceforge.kolmafia.textui.DataFileCache.getR eader(DataFileCache.java:193)
at net.sourceforge.kolmafia.textui.RuntimeLibrary.fil e_to_map(RuntimeLibrary.java:7341)
at net.sourceforge.kolmafia.textui.RuntimeLibrary.fil e_to_map(RuntimeLibrary.java:7332)
at jdk.internal.reflect.GeneratedMethodAccessor189.in voke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl. invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at net.sourceforge.kolmafia.textui.parsetree.LibraryF unction.execute(LibraryFunction.java:104)
at net.sourceforge.kolmafia.textui.parsetree.Function Call.execute(FunctionCall.java:154)
at net.sourceforge.kolmafia.textui.parsetree.BasicSco pe.execute(BasicScope.java:417)
at net.sourceforge.kolmafia.textui.Interpreter.execut eScope(Interpreter.java:393)
at net.sourceforge.kolmafia.textui.Interpreter.execut e(Interpreter.java:341)
at net.sourceforge.kolmafia.textui.Interpreter.execut e(Interpreter.java:334)
at net.sourceforge.kolmafia.request.FightRequest.next Round(FightRequest.java:1041)
at net.sourceforge.kolmafia.request.FightRequest.runO nce(FightRequest.java:1945)
at net.sourceforge.kolmafia.request.FightRequest.run( FightRequest.java:2007)
at net.sourceforge.kolmafia.request.FightRequest.run( FightRequest.java:1978)
at net.sourceforge.kolmafia.webui.RelayAutoCombatThre ad.run(RelayAutoCombatThread.java:76)

Current Mafia Build
 

Darzil

Developer
So, if that zlib.ash is the same as mine, that line is :
file_to_map("vars_"+replace_string(my_name()," ","_")+".txt",vars);

In file_to_map:

String filename = var1.toString();

DataFileCache.getReader( filename );

In getReader we have :

byte[] data = DataFileCache.getBytes( filename );

And do :

return DataUtilities.getReader( new ByteArrayInputStream( data ) );

So I guess there is something wrong with the file.

What is the contents of file "vars_"+replace_string(my_name()," ","_")+".txt" ?
 

Veracity

Developer
Staff member
What Java version are you using? When did you last change or update it?

(Every time we've had this error reported in the past, we've looked at the code and threw up our hands; the error is happening when the ByteInputStream class (supplied by Java) is being initialized.

Every time we've looked at this line - byte[] data = DataFileCache.getBytes( filename ); - we have concluded that it is not possible for the byte array to be null - and therefore we can't be passing a null to the ByteInputStream constructor - even if the NPE wasn't happening during class initialization time, rather than in the constructor.)
 
Last edited:

fronobulax

Developer
Staff member
What is the name of the character running the script?

Is a file named "vars_" <append name of character with spaces replaced with underbars> ".txt" present in the data directory?

Does it appear "reasonable"? It should be a small (a few K) text file with a keyword beginning each line followed by one or more values. Do any of the keywords or values contain special characters or non-ASCII characters?

We have seen similar errors before when a data file gets corrupted. In my copy of zlib the offending line is trying to read the vars file, hence the questions.

Deleting the file and re-running is one obvious test although you probably don't want to do that if you have tweaked script parameters.
 

Veracity

Developer
Staff member
In getReader we have :

byte[] data = DataFileCache.getBytes( filename );

And do :

return DataUtilities.getReader( new ByteArrayInputStream( data ) );
I recall looking at this issue - which has been reported many times in the past - and concluding that the byte[] could not be null.

Suggestion: Put in debugging code following the call to getBytes checking if the byte array is null. If so, log something useful.
 
I haven't updated my Java in a long time. This just started happening yesterday. I will check the var_ file and restore from a backup if needed
 

fronobulax

Developer
Staff member
I recall looking at this issue - which has been reported many times in the past - and concluding that the byte[] could not be null.

Suggestion: Put in debugging code following the call to getBytes checking if the byte array is null. If so, log something useful.

I note that getBytes is static which means there is only one "instance" of it. I note it is also used by Runtimelibrary.load_html(). Since this report starts with a relay combat, is it possible that it is being invoked twice and the invocations are not independent? I'm not sure what I would tweak to prove/disprove this (currently under the influence of adult beverages) but maybe someone else will have an idea (or insert debugging code) before I get a chance?
 

Veracity

Developer
Staff member
I note that getBytes is static which means there is only one "instance" of it. I note it is also used by Runtimelibrary.load_html(). Since this report starts with a relay combat, is it possible that it is being invoked twice and the invocations are not independent? I'm not sure what I would tweak to prove/disprove this (currently under the influence of adult beverages) but maybe someone else will have an idea (or insert debugging code) before I get a chance?
The fact that the method is "static" has nothing to do with whether the return value - a byte array - is static. In fact, the byte array is allocated in ByteBufferUtilities using this method:

Code:
	public static byte[] read( InputStream istream )
	{
		if ( istream == null )
		{
			return EMPTY_BYTE_ARRAY;
		}

		ByteArrayOutputStream ostream = ByteBufferUtilities.getOutputStream();
		ByteBufferUtilities.read( istream, ostream );
		byte[] data = ostream.toByteArray();
		ByteBufferUtilities.returnOutputStream( ostream );

		return data;
	}
According to the documentation for ByteArrayOutputStream, the "toByteArray" method "Creates a newly allocated byte array."
 

xKiv

Active member
And even if it wasn't newly allocated, it wouldn't matter. You can't make some other thread's local variables null by manipulating your thread's variables.
 

fronobulax

Developer
Staff member
static methods with immutable parameters are thread safe. static methods with mutable parameters are not. My first pass suggested some mutable parameters were being used and hence the code was not thread safe. My second pass, today, suggests my first pass was wrong since File and String are immutable and that covers most of the static calls.

Edit: Once again I make a sweeping generalization that is not true as presented and fail to articulate the conditions and assumptions that will make it true. Move on. Nothing to see here.
 
Last edited:

xKiv

Active member
static methods with immutable parameters are thread safe. static methods with mutable parameters are not.

Both of those statements are false.
Immutable parameters don't save you from clobbering class attributes that are currently being used by a different thread ...
... and mutable parameters don't prevent you from properly synchronizing (or even not doing anything potentially thread-unsafe in the first place).

What is probably thread-unsafe is manipulation with DataFileCache.dataFileDataCache and DataFileCache.dataFileTimestampCache (The <tt>HashMap</tt> class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.).

Maybe updateCache and getBytes should be synchronized on dataFileDataCache? And updateCache could maybe print a helpful error message if data==null, just to be safe? Because if that can happen, then getBytes *would* return null for that filename ....
(it's also currently possible to dataFileDataCache.get(filename) while some other thread is in the middle of storing the data for that filename)
 

fronobulax

Developer
Staff member
Both of those statements are false.

I obviously disagree but am fine with resolving that in PM or not at all. If my mistakes and our disagreement leads to someone fixing a problem and the problem something was thread-unsafe then I am content.
 

fronobulax

Developer
Staff member
I decided xKiv was making more sense than I was and implemented what I thought was his suggestion.

r18985
 
Top