什么scala语句或代码可以生成一个无法转换为java的字节码?

Che*_*rry 9 java scala bytecode

我已经阅读了关于将Scala代码转换为Java代码的问题的答案.它说:

我不认为将scala转换回标准java是可能的,因为Scala做了一些相当低级别的字节码操作.我90%肯定他们做了一些不能完全转换回普通Java代码的东西.

那么Scala语句或代码可以产生无法转换为java的字节码?

PS我通常同意这个答案,但想要一个具体的例子用于学习目的.

Ant*_*ony 8

答案实际上取决于您想要尝试转换代码的难度.

由于Java和Scala都是完整的,因此任何一个程序都可以简单地转换为另一个程序,但这并不是真正有趣或有用.

你真正想要的是将结果转换为可读的惯用代码.从这个角度来看,即使Java代码也不能自动转换为Java,因为编译会丢失信息(虽然与C相比相对较少),并且机器在编写人类可读代码时并不如人类好.

如果您有Java和Scala专家,他们可能会用Java重写您的Scala代码库,最终会得到合理惯用的Java代码.但它不像Scala那样可读,因为Scala是一种旨在改进Java的语言.Scala尝试从Java中删除疣并提供强大的高级编程功能,无需使用所有经典的Java样板.因此,Java等效代码库将不具有可读性.

从这个角度来看,答案是"Scala中没有Java的任何功能".

  • 你应该说"*可能*不像Java那样可读".有一些时间需要付出代价才能得到简洁,而这通常会损害可读性. (2认同)

ggo*_*van 6

Scala的嵌套块没有Java等价物.

Scala中的嵌套块(取自此问题):

def apply(x: Boolean) = new Tuple2(null, {
  while (x) { }
  null
})
Run Code Online (Sandbox Code Playgroud)

生成字节码

 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   
Run Code Online (Sandbox Code Playgroud)

在指令0处,未初始化的对象被推入堆栈,然后在指令10处初始化.在这两个点之间存在从6到5的向后跳跃.这实际上揭示了OpenJDK字节码验证器中的错误,因为它拒绝此代码,尽管事实上,JVM规范可以接受它.这可能是通过测试得出的,因为这个字节码不能从Java生成.

与Java中一样,嵌套块不是计算值的表达式,而是最接近的Java等价物

public Tuple2 apply(boolean x){
  while(x){}
  return new Tuple2(null,null);
}
Run Code Online (Sandbox Code Playgroud)

哪个会编译成类似的东西

 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
Run Code Online (Sandbox Code Playgroud)

请注意,这在向后跳转时堆栈上没有未初始化的对象.(NB字节码是手写的,不执行!)


来自Li,White和Singer的这篇论文展示了JVM语言的差异,包括它们编译的字节码.它发现在字节码的N-gram分析中,在Java执行的字节码中找不到Scala执行的4 -g的58.5%.这并不是说Java 不能生成这些字节码,而是它们不存在于Java语料库中.


clo*_*oud -4

我认为没有这样的代码。AFAIK 只有一条 java 无法生成的 jvm 指令——invoke_dynamic。该指令适用于动态语言,而 scala 是静态类型语言,这意味着它也无法生成它。因此可以将 scala 代码转换为 java 代码,甚至可能是不可读的 java 代码。