The following behaviour was found with janino 2.1.0
running on a sun JVM 1.4.2_06-b03
under Win2K:
The class net.janino.Compiler throws an
ArrayOutOfBoundsException if you try to compile the
very simple programs Test1.java or Test2.java. It
throws a RuntimeException (operand stack underrun) if
you try to compile Test3.java.
All three test programs are enclosed in the attachment
to this bug report and you have to split the attachment
by hand into three java files.
With a little research, we found out, that the problem
doesn't show up using SimpleCompiler, because
SimpleCompiler doesn't use an ErrorHandler allowing
more than one error during compilation. We further
found out, that the
problem seems related to synchronisation after the
error is reported. Janino tries to go on and code a
constructor invocation though no applicable constructor
exists. This happens in method
Java.invokeConstructor(), presumably around line 6721.
The called method Java.findMostSpecificIInvocable()
returns an IClass.IConstructor even if no suitable
constructor could be found (and an ErrorHandler was
set). This causes parameterTypes.length and
arguments.length to be different for three test
programs. So you either get an
ArrayOutOfBoundsException or a RuntimeException
(operand stack underrun).
We don't know much about the janino sourcecode but one
solution may be to return null from
Java.findMostSpecificIInvocable() if there's no
applicable constructor and to return from
Java.invokeConstructor() without trying to evaluate the
arguments and to code the constructor invocation.
Because Java.findMostSpecificIInvocable() is called in
more places than inside Java.invokeConstructor() there
are probably more changes needed if one tries to
realize this approach.
Thanks for providing us with such a helpful piece of
software. Keep on the good work.
Matthias Eichel & Judith Andres
Three buggy Java programs enclosed in one file
Logged In: YES
user_id=865893
Thank you for your detailed bug report.
The solution is that "findMostSpecificInvocable()" must be
more careful when returning the fake IInvocable,
particularly, its agrumentTypes have to be appropriate.
The semantics of "compileError()" is
/**
* Issue a compile error with the given message. This is
done through the
* {@link ErrorHandler} that was installed through
* {@link #setCompileErrorHandler(ErrorHandler)}. Such a
handler typically throws
* a {@link CompileException}, but it may as well decide
to return normally. Consequently,
* the calling code must be prepared that {@link
#compileError(String, Scanner.Location)}
* returns normally, and must attempt to continue compiling.
*
* @param message The message to report
* @param optionalLocation The location to report
*/
(I added this documentation in the source code to make
things clear.)
The fix will be released with the next (>2.1.0) version of
JANINO. If you need a quick fix, use the DIFF attached.
The next version of JANINO is not scheduled yet.
By the way, I'm always curiouos... how are you using JANINO?
(Please respond to maintainer@janino.net.)