What scala statements or code can produce bytecode that cannot be translated into java?

I read the answer to a question about converting Scala code to Java code. It says:

I do not think that it is possible to convert from Scala back to standard java, since Scala does some fairly low-level manipulations with byte code. I am 90% sure that they are doing some things that cannot be accurately translated back to normal Java code.

So, what kind of statements or Scala code can generate bytecode that cannot be translated into java?

PS I agree with this answer, but I want a concrete example for educational purposes.

+8
java scala bytecode
source share
6 answers

The answer really depends on how difficult you want to convert the code.

Since Java and Scala are complete, any program in one can be trivially converted to another, but this is not very interesting or useful.

You really want to convert the results into readable, idiomatic code. From this point of view, even Java code cannot be automatically converted to Java, because compilation loses information (although relatively small compared to C), and machines are not as good as people when writing human readable code, anyway .

If you have Java and a Scala expert, they can probably rewrite your Scala code base in Java and end up with enough idiomatic Java code. But it would not be as easy to read as Scala because of the simple fact that Scala is a language designed to improve in Java. Scala attempts to remove warts from Java and provides powerful, high-level programming features, eliminating the need for an entire classic Java pattern. Thus, the equivalent Java code base will not be as readable.

From this point of view, the answer is "any function in Scala that is not in Java."

+8
source share

Scala Nested blocks have no Java equivalent.

Nested block in Scala (taken from this question ):

def apply(x: Boolean) = new Tuple2(null, { while (x) { } null }) 

Produces bytecode

  0: new #12 // class scala/Tuple2 3: dup 4: aconst_null 5: iload_1 6: ifne 5 9: aconst_null 10: invokespecial #16 // Method scala/Tuple2."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V 13: areturn 

In instruction 0, an uninitialized object is pushed onto the stack and then initialized in command 10. Between these two points, the transition from 6 to 5 takes place. This actually shows an error in the OpenJDK bytecode verifier, since it rejects this despite the fact that this is acceptable according to JVM specifications. This probably happened through testing since this bytecode could not be generated with Java.

As in Java, nested blocks are not expressions that evaluate the value, then the closest equivalent to Java will be

 public Tuple2 apply(boolean x){ while(x){} return new Tuple2(null,null); } 

To compile something similar to

  0: iload_1 1: ifne 0 3: new #12 // class scala/Tuple2 6: dup 7: aconst_null 8: dup 9: invokespecial #16 // Method scala/Tuple2."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V 12: areturn 

Note that this does not have an uninitialized object on the stack during the jumpback. (NB bytecode was written by hand, do not execute!)


This article by Lee, White, and Singer shows differences in JVM languages, including the bytecode they compile. He found that in N-gram bytecode analysis, 58.5% of the 4-grams performed by Scala were not found in the bytecode executed by Java. This does not mean that Java cannot generate these bytecodes, but they are not present in the Java enclosure.

+6
source share

As you noted, Scala eventually compiles to JVM bytecode. An obvious JVM instruction set instruction that has no Java equivalent is goto .

The Scala compiler can use goto to optimize loops or tail recursive methods. In this case, in Java you will need to emulate goto behavior.

As Antimony hinted, Turing's complete language can at least mimic another Turing language. However, the resulting program can be difficult and suboptimal.

As a final note, decompilers can help. I am not familiar with internal decompilers, but I believe that they rely a lot on templates. I mean, for example, that the original Java f (x) pattern is compiled into the bytecode pattern f '(x), so with a lot of work and experience, some manage to decompile Bytecode f' (y) to the Java source f (y).

However, I have not heard of Scala decompilers yet (maybe someone is working on this).

[EDIT] About what I originally meant by emulating goto behavior:

I had in mind the switch/case expressions inside the loop, and cdshines showed a different way using the labeled break/continue in the loop (although I believe that using “ignored and convicted” functions is not standard).

In either of these cases, to return to an earlier instruction, you need the idiomatic Java loop ( for/while/do-while ) (any other suggestion?). An infinite loop makes it easy to implement, a conditional loop will require more work, but I assume that it is doable.

In addition, goto not limited to loops. To speed up the transition, Java will require other solutions.

Counterexample: C has limitations, but you don’t need to go through such long lengths because there is a goto .

As a related topic, if you are interested in non-idiomatic jumping in Scala, cf this old Q & A is mine . I believe that not only the Scala compiler can generate goto in a way that is not natural in Java, but the developer can have tight control over this with Scala macros.

LabelDef : tagged expression. It is not expressed in the syntax of the language, but is generated by the compiler to simulate while / do-while loops, as well as using a template. In my past tests, it can also be used for advanced transitions. At Scala Internals, developers wrote about removing LabelDef , but I don’t know if and when they will be.

So yes, you can reproduce goto behavior in Java, but because of the complexity involved, this is not what I would call standard Java, IMHO. Perhaps my formulation is incorrect, but, in my opinion, the reproduction of elementary behavior by complex means is an “emulation" of this behavior.

Greetings.

+2
source share

It really depends on how you define. So, what kind of statements or Scala code can generate bytecode that cannot be translated into java ?.

Ultimately, some of the functions of Scala are supported by the so-called ScalaSignature (scala signature), which stores meta-information. Starting from 2.10, this can be considered as a secret api, which is abstracted by Scala reflection mechanisms (which are radically different from java reflection). The documentation is small, but you can check this pdf to get detailed information (since then, serious changes may occur). It is not possible to create identical structures in native Java unless you use bytecode manipulation tools.

In a more relaxed sense, there are macros and implications that interact exclusively with a scalar and have no direct analogue in java. Yes, you can write java code identical to the result generated by scalac, but you cannot write these dynamic instructions that the compiler will direct.

+1
source share

I have to work with a lot of byte code, and I once wrote a summary of the byte code functions that cannot be reproduced by writing Java code. However, all of these non-existent functions are rather conventions for writing byte code instructions. In Java 8, any existing opcode was used by the Java class file format. This is not too surprising since the Java type language controls the evolution of the Java byte code format. An exception may be the INVOKEDYNAMIC command, which was introduced to improve support for dynamic languages ​​in the JVM, but even this instruction is used in Java 8 to implement lambda expressions. Thus, there may be combinations / orders of byte code commands that are not created by the javac compiler, but there is no specific instruction that is used only in another JVM language.

From the bytecode that I named in the summary, I would say that throwing unannounced checked exceptions without catching them is a function supported by Scala, but not using Java. Otherwise, however, I would say that low-level manipulation of byte code is not performed using scalars unknown to javac. In my experience, most Scala classes can also be explicitly written in Java.

+1
source share

I think there is no such code. AFAIK there is only one jvm instruction that java cannot generate - invoke_dynamic. This instruction is for a dynamic language, and scala is a static type language, which means that it also cannot generate it. Thus, you can translate scala code into java code and possibly unreadable Java code.

-4
source share

All Articles