java - java内部在什么地方运行异常

标签 java jvm java-native-interface

我想知道JVM或JDK是如何运行异常的。例如,如果我们有数组

int tab[] = {1,2,3};

我们尝试访问

选项卡[10]

JVM运行ArrayIndexOutOfBoundsException没问题。是否可以看到该异常在 JDK 或 JVM 的哪个部分执行?我的意思是抛出 new ArrayIndexOutOfBoundsException() 或类似的东西?难道从调用JNI调用就不可能了吗?

最佳答案

首先,参见this answer简单概述异常在 HotSpot JVM 中如何工作。

对于抛出ArrayIndexOutOfBoundsException的JVM代码,有多个地方可以看到:

  1. 口译员。解释器中的 iaload 字节码(以及其他数组访问字节码)的实现包括索引检查。如果检查失败,解释器将跳转到异常抛出 stub 。请参阅templateTable_x86.cpp :

    void TemplateTable::iaload() {
      transition(itos, itos);
      // rax: index
      // rdx: array
      index_check(rdx, rax); // kills rbx                              --------------
      __ access_load_at(T_INT, IN_HEAP | IS_ARRAY, rax,                             |
                        Address(rdx, rax, Address::times_4,                         |
                                arrayOopDesc::base_offset_in_bytes(T_INT)),         |
                        noreg, noreg);                                              |
    }                                                                               |
                                                                                    |
    void TemplateTable::index_check(Register array, Register index) {             <--
      // Pop ptr into array                                                          
      __ pop_ptr(array);                                                             
      index_check_without_pop(array, index);                           --------------
    }                                                                               |
                                                                                    |
    void TemplateTable::index_check_without_pop(Register array, Register index) { <--
      // destroys rbx
      // check array
      __ null_check(array, arrayOopDesc::length_offset_in_bytes());
      // sign extend index for use by indexed load
      __ movl2ptr(index, index);
      // check index
      __ cmpl(index, Address(array, arrayOopDesc::length_offset_in_bytes()));
      if (index != rbx) {
        // ??? convention: move aberrant index into rbx for exception message
        assert(rbx != array, "different registers");
        __ movl(rbx, index);
      }
      Label skip;
      __ jccb(Assembler::below, skip);
      // Pass array to create more detailed exceptions.
      __ mov(NOT_LP64(rax) LP64_ONLY(c_rarg1), array);
      __ jump(ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry));  !!!
      __ bind(skip);
    }
    
  2. JIT 编译器(C1 和 C2)。当方法经过 JIT 编译时,编译器会在生成的机器代码中包含类似的索引检查序列。有时,当编译器可以证明不会发生越界条件时,它会消除冗余检查。

    例如,C1 编译器首先在中间表示中发出与平台无关的范围检查,请参阅 c1_LIRGenerator.cpp :

    void LIRGenerator::array_range_check(LIR_Opr array, LIR_Opr index,
                                        CodeEmitInfo* null_check_info, CodeEmitInfo* range_check_info) {
      CodeStub* stub = new RangeCheckStub(range_check_info, index, array);
      if (index->is_constant()) {
        cmp_mem_int(lir_cond_belowEqual, array, arrayOopDesc::length_offset_in_bytes(),
                    index->as_jint(), null_check_info);
        __ branch(lir_cond_belowEqual, T_INT, stub); // forward branch
      } else {
        cmp_reg_mem(lir_cond_aboveEqual, index, array,
                    arrayOopDesc::length_offset_in_bytes(), T_INT, null_check_info);
        __ branch(lir_cond_aboveEqual, T_INT, stub); // forward branch
      }
    }
    

    然后在代码生成期间,RangeCheckStub 扩展为依赖于平台的程序集,其中包括跳转到异常抛出 stub ,请参阅 c1_CodeStubs_x86.cpp :

      if (_throw_index_out_of_bounds_exception) {
        stub_id = Runtime1::throw_index_exception_id;
      } else {
        stub_id = Runtime1::throw_range_check_failed_id;
        ce->store_parameter(_array->as_pointer_register(), 1);
      }
      __ call(RuntimeAddress(Runtime1::entry_for(stub_id)));
    

    最后,这会导致调用 Exceptions::_throw JVM C++ 代码中的函数。

关于java - java内部在什么地方运行异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53456703/

相关文章:

java - Signal R native Android 应用程序协商失败

java - 如何修复java.lang.UnsupportedClassVersionError:不支持的major.minor版本

android - 使用 JNI(更具体地说是 Android NDK)时,Java 是否通过引用或值传递给 C

java - 如何使用使 C 程序部分调用 JNI 中的 .a 库

java - 步骤定义 Java - Selenium WebDriver 从搜索结果中查找元素

java - 错误 : java. lang.ClassCastException

Java:.jsp 中的属性顺序颠倒

java.lang.VerifyError 构造函数调用

java - JVM 上的汇编编程?

android - 加载 .so 文件在某些​​ Android 设备上崩溃