Closed bys1 closed 1 year ago
When I decompile Test.class
, the constructor is as follows:
decl(
array(string()),
"args"),
invokeSuper(
constructorDesc([]),
[]),
store(
"args",
newArray(
object("Ljava.lang.String"),
const(
integer(),
3))),
return()
When I compile the following Java class using javac
:
public final class Test2 {
public Test2() {
String[] args = new String[3];
}
}
and decompile it with Flybytes, the constructor is:
asm([
ALOAD(0,LINE=6),
INVOKESPECIAL(
object("java.lang.Object"),
constructorDesc([]),
false,
LINE=6)
]),
do(newArray(
string(),
const(
integer(),
3))),
asm([ASTORE(1,LINE=6)]),
return()
So in the Flybytes-compiled Test
file, it calls newArray
with the type object("Ljava.lang.String")
and in Test2
, string()
is used. Note that when compiling using Flybytes, I cannot use newArray
with string()
, but have to use array(string())
instead, because otherwise I get the following error:
|jar+file:///Users/bys1/.m2/repository/org/rascalmpl/flybytes/0.1.10/flybytes-0.1.10.jar!/src/lang/flybytes/Compiler.rsc|(1637,272,<25,0>,<27,123>): Java("IllegalArgumentException","arg should be an array type")
at lang.flybytes.internal.ClassCompiler$Compile.newArrayExp(|unknown:///ClassCompiler.java|(0,0,<2687,0>,<2687,0>))
at lang.flybytes.internal.ClassCompiler$Compile.expr(|unknown:///ClassCompiler.java|(0,0,<2247,0>,<2247,0>))
at lang.flybytes.internal.ClassCompiler$Compile.storeStat(|unknown:///ClassCompiler.java|(0,0,<2134,0>,<2134,0>))
at lang.flybytes.internal.ClassCompiler$Compile.declareVariable(|unknown:///ClassCompiler.java|(0,0,<703,0>,<703,0>))
at lang.flybytes.internal.ClassCompiler$Compile.declStat(|unknown:///ClassCompiler.java|(0,0,<2038,0>,<2038,0>))
at lang.flybytes.internal.ClassCompiler$Compile.statement(|unknown:///ClassCompiler.java|(0,0,<831,0>,<831,0>))
at lang.flybytes.internal.ClassCompiler$Compile.statements(|unknown:///ClassCompiler.java|(0,0,<812,0>,<812,0>))
at lang.flybytes.internal.ClassCompiler$Compile.method(|unknown:///ClassCompiler.java|(0,0,<646,0>,<646,0>))
at lang.flybytes.internal.ClassCompiler$Compile.methods(|unknown:///ClassCompiler.java|(0,0,<535,0>,<535,0>))
at lang.flybytes.internal.ClassCompiler$Compile.compileClass(|unknown:///ClassCompiler.java|(0,0,<345,0>,<345,0>))
at lang.flybytes.internal.ClassCompiler.compileClass(|unknown:///ClassCompiler.java|(0,0,<104,0>,<104,0>))
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(|unknown:///NativeMethodAccessorImpl.java|(0,0,<0,0>,<0,0>))
at compileClass(|jar+file:///Users/bys1/.m2/repository/org/rascalmpl/flybytes/0.1.10/flybytes-0.1.10.jar!/src/lang/flybytes/Compiler.rsc|(1902,5,<27,116>,<27,121>))
at $shell$(|prompt:///|(0,11,<1,0>,<1,11>)ok
rascal>
I just found out that I do NOT get the LinkageError/ClassFormatError when explicitly giving the String class rather than using the string()
type:
\decl(array(string()), "args", init = newArray(
array(object("java.lang.String")),
iconst(3)
)),
Using newArray
with array(object("java.lang.String"))
rather than array(string())
works fine.
That's very nice analysis. I can probably fix this bug based on your input. Maybe tomorrow. Today the time is up.
Note to self: typically string()
should act as a simple alias for object("java.lang.String")
. Possibly in the code for generating array declarations I missed a case distinction.
I am compiling a
Test.class
file by calling the following function:When running this using
java Test
I get the following error in the terminal:In case it helps you: I got a stack trace in the Rascal shell when I tried loading a bigger class file using a classloader:
The error does not appear when removing the
decl
part from the code above.