【问题标题】:What is the process of runtime execution in java and how does JVM checks for array types at run time?java中运行时执行的过程是什么,JVM在运行时如何检查数组类型?
【发布时间】:2020-12-27 13:54:58
【问题描述】:

我正在阅读有关泛型和类型安全的内容,发现数组在 java 中不能是泛型的。我还理解了数组的协变性质,这将我引向了数组存储异常。我明白为什么会出现这个异常。

我试过下面的代码

class SuperClass {
    
}

class SubClass extends SuperClass {
    
}
public class ArrayCheck {
    
    public static void main (String args[]) {   
        SubClass arr[] = new SubClass[10];
        
        arr[0] = new SubClass();
        
        SuperClass[] arr1 = arr;
        arr1[1] = new SuperClass();
        
    }
}

这如预期的那样给出了 ArrayStoreException。我的问题是

  1. 我的问题是 JVM 如何在运行时检查数组类型? 编译器是否附加了任何额外的代码,或者 JVM 在执行指令之前是否遵循了一些预定义的过程?

  2. 在什么时候引发了这个异常? 我认为ArrayStoreException 只有在我尝试读取数组时才会出现,但我错了。所以我不明白这个错误究竟是在什么时候提出的。

另外,需要说明一下Java程序的执行过程。

  1. 运行时错误和异常仅是程序执行时发生的错误,即 JVM 已开始解释和执行指令或字节码验证期间的错误也被视为运行时错误。

【问题讨论】:

  • 当您尝试将某些内容 storearray 时,您会得到 ArrayStoreException(因为您尝试将无效元素存储到数组中),当您尝试从 arrayread 某些内容时,您会得到 ClassCastException(因为它会将数组中的元素隐式转换为接收器类型)。关于错误:What is the difference between run-time error and compiler error?
  • @Asim 现在我只是假设,因为我看到的规范只提到异常被抛出,但不是在那个时候。因为数组访问的逻辑不是在java中实现的,而是在较低级别上,所以必须在“native-layer”中抛出检查(只是不是java-code)。另外关于你关于数组类型的问题,这是我发现的唯一东西 (docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#jls-10.8),虽然我还没有搜索到那么远。也许this 也有帮助
  • 提示:一旦你开始对问题中的独立子问题进行编号......你就错了。这个想法是你的问题在这里......包含一个问题,而不是多个。
  • 我不明白为什么人们会在脑海中编造一些东西或阅读有问题的文章,而不是从官方权威来源开始。来自the documentation of ArrayStoreException:“抛出表示试图将错误类型的对象存储到对象数组中。例如,以下代码生成 ArrayStoreException:Object x[] = new String[3]; x[0] = new Integer(0);”。那么如何假设在读取操作时会抛出异常呢?
  • 我不认为你没有读过它,我问为什么在做出错误假设和做实验之前你没有开始阅读它。文档很清楚,并提供了一个示例。因此,如果您阅读了它,为什么还要问“在什么时候”会抛出异常?此外,您有一个示例代码会产生这样的异常,并且可以查看堆栈跟踪以准确查看异常在哪个行号被抛出。那么问题是什么?

标签: java arrays jvm strong-typing


【解决方案1】:

我的问题是 JVM 如何在运行时检查数组类型?

当JVM解释字节码时,解释器在解释aastore字节码指令时会执行相关的运行时类型检查。相关的 JVM 规范链接是 https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.aastore

JIT 编译器会将aastore 指令翻译成执行相同操作的本机代码,尽管它可能优化任何可以确定为冗余的类型检查。

请注意,只有在您调整字节码以尝试将引用分配给原始类型的数组时,这种事情才会引起验证者的注意。

这个异常是在什么时候引发的?

当您将一个值分配给某个引用类型的数组并且您分配的值与数组的基本类型不分配兼容时。

(请注意,原始类型的数组不会引发异常。如果您尝试将long 分配给int[] 或将boolean 分配给int[],您将收到编译错误。如果您尝试将 int 分配给 long[],则该值将被扩大。)

【讨论】:

  • 感谢您的链接。我认为 JVM 指令集文档确实有帮助。
猜你喜欢
  • 2011-12-04
  • 1970-01-01
  • 2013-11-02
  • 2020-06-20
  • 2021-10-11
  • 2022-12-09
  • 1970-01-01
  • 2014-06-02
  • 2011-09-09
相关资源
最近更新 更多