标签: jvm-bytecode

变量'final'修饰符在字节码中丢失了?

分析这个简单类的字节码,我得出的结论是编译器不保留有关局部变量的任何信息final.这看起来很奇怪,因为我相信HotSpot编译器实际上可以使用这些信息来进行优化.

代码:

public static void main(String[] args)
{
    final int i = 10;
    System.out.println(i);
}
Run Code Online (Sandbox Code Playgroud)

字节码:

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=2, locals=2, args_size=1
     0: bipush        10
     2: istore_1      
     3: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
     6: bipush        10
     8: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
    11: return        
  LineNumberTable:
    line 7: 0
    line 8: 3
    line 9: 11
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
        0      12     0  args   [Ljava/lang/String;
        3       9     1     i …
Run Code Online (Sandbox Code Playgroud)

java jvm final jvm-bytecode

7
推荐指数
1
解决办法
371
查看次数

为什么java字节码"存储"通常后跟"加载"?

当我从一些小的java函数中读取jvm字节码时,我发现当一个新的局部变量在操作数堆栈上计算时,假设它将存储在局部变量表中,但通常它会立即加载到操作数堆栈中(仅字面上的字节码).我操作不好,是不必要的操作?

java bytecode jvm-bytecode

7
推荐指数
2
解决办法
468
查看次数

Kotlin内联扩展属性

我知道内联关键字的意思是避免调用功能的调用开销。但是我不知道扩展属性可以用于什么内联?

假设我们有两个名为foo的扩展属性,另一个带有名为bar的内联属性

val Any.foo : Long
    get() = Date().time

inline val Any.bar : Long
    get() = Date().time
Run Code Online (Sandbox Code Playgroud)

执行其中的任何一个,我们将期望的输出,即当前时间。

该文件的字节码如下:

val Any.foo : Long
    get() = Date().time

inline val Any.bar : Long
    get() = Date().time
Run Code Online (Sandbox Code Playgroud)

我们可以看到两者相似,但仅在以下几行不同:

foo提取:

    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1
Run Code Online (Sandbox Code Playgroud)

酒吧摘录:

    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    LOCALVARIABLE $i$f$getBar I L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2
Run Code Online (Sandbox Code Playgroud)

我真的不明白这里发生了什么。有人可以指点我看一下它的行为,或java中的等效行为,或对此的一些用法吗?

编辑

给定编译器将替换内联属性的内容,可以方便地内联每个没有繁重操作的扩展属性。

谢谢

inline kotlin kotlin-extension jvm-bytecode

7
推荐指数
1
解决办法
1249
查看次数

Java 8:验证字节码时将 String[] 和 int[] 合并到 Object[] 中

我正在阅读 JVM 版本 8 规范的第 4.10.2.2 节(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html)如何验证字节码。在这种情况下,当堆栈现在包含一个槽时,如果来自一个源,则包含一个 int[] ;如果来自另一个源,则包含一个 String[] ,控制流中会发生什么情况。

我阅读了以下内容,该内容在 JVM 版本 7 文档中不存在:

如果对应的值都是数组引用类型,则检查它们的维度。如果数组类型具有相同的维度,则合并的值是对数组类型实例的引用,该数组类型是两种数组类型的第一个公共超类型。(如果其中一个或两个数组类型具有原始元素类型,则使用 Object 作为元素类型。)

...

甚至int[]和String[]也可以合并;结果是 Object[],因为在计算第一个公共超类型时使用了 Object 而不是 int。

这对我来说没有任何意义,因为这意味着 int[] 可以转换为 Object[]。但在 Java 中,原始类型的数组不能转换为 Object[]。

谁能解释一下这背后的理由吗?

java jvm bytecode jvm-bytecode

6
推荐指数
1
解决办法
128
查看次数

Java字节码是否始终向前兼容?

我知道,只要Y> = X,就可以保证版本JDK X生成的字节码可以在JVM Y上运行。

这对所有版本的JDK / JVM都适用吗?即期望JDK 1生成的类文件在JVM 11上运行是否公平?

参考JVM规范JDK 8兼容性指南Java 11 JSR 在那里找不到精确的答案。

java compatibility jvm jvm-bytecode

6
推荐指数
2
解决办法
786
查看次数

在箭头 (->) 的帮助下切换表达式,现在可以产生/返回值

Java 14 中扩展的 switch 表达式,除了程序员/审阅者的视觉清晰度之外,switch 表达式的需求并不明确。是吗

  1. 与旧的 switch 表达式不同的字节码实现?
  2. 与以前的版本相比,执行方面有任何性能改进吗?

参考: https: //www.techgeeknext.com/java/java14-features

JDK 14版本:

 int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};
Run Code Online (Sandbox Code Playgroud)

JDK 14 字节代码

   0: iconst_1
   1: istore_1
   2: iload_1
   3: tableswitch   { // 1 to 7
                 1: 44
                 2: 44
                 3: 44
                 4: 49
                 5: 54
                 6: 54
                 7: 59
           default: 64
      }
  44: bipush        6
  46: goto          65 …
Run Code Online (Sandbox Code Playgroud)

java performance switch-statement jvm-bytecode java-14

6
推荐指数
1
解决办法
2万
查看次数

bipush 在 JVM 中是如何工作的?

我知道 iload 接受整数 -1 到 5,但是如何使用 bipush 指令扩展到更高的数字?特定整数如何与字节码一起存储?

java jvm jvm-bytecode

5
推荐指数
2
解决办法
4130
查看次数

为什么 AspectJ 生成空的 Annotation 检查?

我正在使用 AspectJ 1.8.8 编译时编织,并且我有一个像这样的块

@SomeAnnotation(value="someValue")
public List doSomething(String someArg) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

where@SomeAnnotation是通过“Around”建议实现的。

使用 JD-GUI 查看字节码,我看到以下生成的代码(略有格式):

public class SomeClass {
  private static Annotation ajc$anno$5;

  ...

  @SomeAnnotation(value="someValue")
  public List doSomething(String someArg)
  {
    String str = someArg;
    JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_5, this, this, str);
    Object[] arrayOfObject = new Object[3];
    arrayOfObject[0] = this;
    arrayOfObject[1] = str;
    arrayOfObject[2] = localJoinPoint;
    Annotation tmp56_53 = ajc$anno$5;
    if (tmp56_53 == null) {
      tmp56_53;
    }
    return (List)new SomeClass.AjcClosure11(arrayOfObject).linkClosureAndJoinPoint(69648).around(tmp56_53, (SomeAnnotation)(ajc$anno$5 = SomeClass.class.getDeclaredMethod("doSomething", new Class[] { String.class }).getAnnotation(SomeAnnotation.class))); …
Run Code Online (Sandbox Code Playgroud)

java aop aspectj jd-gui jvm-bytecode

5
推荐指数
1
解决办法
172
查看次数

Mindustry Game CPU 架构的最简单编译器

我玩了一个很棒的沙盒塔防游戏Mindustry

很酷的事情是您可以使用游戏嵌入式处理器块来控制单元。你可以命令他们建造积木、在地图上巡逻、包围最弱的敌人、治疗朋友并将弹药带到炮塔。

有一些示例如何对此类块进行“编程”:

一些“文档”可以在这里找到:

问题是处理器“语言”非常原始。只有一个控制语句:jump-to-line-if-statement-is-true. 没有 if/else 语句,没有 for 循环,没有函数和类。因此,使用这些指令编写任何复杂的东西几乎是不可能的。

所以我的想法是让我自己的简单编译器从“真正的”编程语言(带有 if、else、for、function、struct/class)到这些原始指令,然后将其导出到游戏中。

我的第一个想法是在 Mindustry 中实现 JVM 或 LLVM-IR VirtualMachine 来运行编译后的字节码,但它看起来很复杂。这些字节码中有很多指令。

然后我考虑实现 Lua 或简化的 Python 解释器,它看起来是可能的,但无论如何这是一项艰巨的工作:-)

我很好奇最简单的方法:-) 也许有基于 ~10 条指令或一些示例项目的简化 JVM/LLVM 字节码,或者在 Brainfuck 或一些有限的架构上运行 Lua/Python :-)

====嵌入式CPU语言====

所以控制指令集是:

  • read - 从 PermanentStorage 地址读取数据到变量
  • write - 将数据从变量写入到 PermanentStorage
  • set - 设置变量数据
  • 链接 - 从数组中获取第 i 个元素
  • operator op add result x y~ result=x+y- 将变量设置为 arifmethics 操作的结果 + - * / …

compiler-construction interpreter bytecode llvm-ir jvm-bytecode

5
推荐指数
0
解决办法
1665
查看次数

为方法引用生成的 getClass 调用的值是多少?

我有以下人为的代码示例。为了保持字节码较小,它没有做任何有用的事情,但希望您可以看到,通过一些更改,它会如何发挥作用。

List<String> letters = Arrays.asList("a", "b");
Stream.of(/*a, b, c, d*/).filter(letters::contains).toArray(String[]::new);
Run Code Online (Sandbox Code Playgroud)

Java 8 生成以下字节码

  public Main();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=2, args_size=1
        start local 0 // Main this
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: iconst_2
         5: anewarray     #2                  // class java/lang/String
         8: dup
         9: iconst_0
        10: ldc           #3                  // String a
        12: aastore
        13: dup
        14: iconst_1
        15: ldc           #4                  // String b
        17: aastore
        18: invokestatic  #5                  // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
        21: astore_1
        start local 1 …
Run Code Online (Sandbox Code Playgroud)

java java-8 jvm-bytecode

5
推荐指数
1
解决办法
152
查看次数