gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 01:59:14 24 4
gpt4 key购买 nike

我想知道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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com