当前位置: 首页 > 面试题库 >

如果缺少未使用的类,JVM会抛出异常吗?

颛孙炜
2023-03-14
问题内容

考虑一下程序:

public class Test {

    public static void main(String[] args) {
        if (Arrays.asList(args).contains("--withFoo")) {
            use(new Foo());
        }
    }

    static void use(Foo foo) {
        // do something with foo
    }
}

如果程序不带参数启动,则运行时类路径中是否需要Foo?

研究

报告链接错误时,Java语言规范相当模糊:

该规范为实现链接活动(以及由于递归,加载)的发生时间提供了实现上的灵活性,前提是尊重Java编程语言的语义,并且在初始化类或接口之前已对其进行了完全验证和准备,并且在链接过程中检测到的错误被抛出到程序中某个位置,在该位置程序执行了一些可能需要链接到错误所涉及的类或接口的操作。

我的测试表明,仅在我实际使用时抛出LinkageErrors Foo

$ rm Foo.class

$ java Test

$ java Test --withFoo

Exception in thread "main" java.lang.NoClassDefFoundError: Foo
        at Test.main(Test.java:11)
Caused by: java.lang.ClassNotFoundException: Foo
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 1 more

可以依靠这种行为吗?还是有主流的JVM链接未使用的代码?如果是这样,我如何隔离未使用的代码,以便仅在需要时才进行链接?


问题答案:

您只需对测试代码进行少量更改即可回答该问题。

将类型层次结构更改为

class Bar {}
class Foo extends Bar {}

和程序

public class Test {
    public static void main(String[] args) {
        if (Arrays.asList(args).contains("--withFoo")) {
            use(new Foo());
        }
    }
    static void use(Bar foo) {
        // don't need actual code
    }
}

现在,Foo即使没有输入main方法(使用HotSpot),该程序也会因错误(如果不存在)而失败。原因是验证者需要定义Foo来检查将其传递给期望的方法Bar是否有效。

如果类型完全匹配或目标类型为java.lang.Object,则HotSpot会采用捷径,而不是加载类型,其中分配始终有效。这就是为什么您的原始代码不在时不会提早抛出的原因Foo

最重要的是,抛出错误的确切时间点取决于实现,例如,可能取决于实际的验证程序实现。正如您已经提到的,所保证的全部是,尝试执行需要链接的动作将引发先前检测到的链接错误。但是,您的程序很可能从未尝试过。



 类似资料:
  • 我知道JVM有一个异常表,它映射在给定字节码索引中可以抛出的可能异常。我还读到athrow字节码抛出了堆栈顶部存在的引用类型的exception。我的问题更多地涉及像irem这样的指令如何“抛出”异常。 JVM是否会在每次指令执行后检查堆栈的顶部,以检查是否存在异常?如果你能洞察到这件事的话,你会很感激的。

  • 抛出异常的行为是否可能抛出不同的异常? 为了抛出异常,必须(可选地)分配新对象,并调用其构造函数(隐式调用fillinstacktrace)。在某些情况下,听起来像addSupressed也被称为。那么如果没有足够的内存会发生什么呢?JVM是否需要预分配内置异常?例如,(1/0)会抛出OutOfMemoryError而不是ArithmeticException吗? 此外,构造函数是一个方法调用,因

  • 与Spring Reactor类似:当publisher发出值时,如何引发异常? 我在DAO中有一个finder方法,它返回结果SomePojo。finder调用amazon db API和具有调用的输出。所以我在我的服务层createSomePojo方法中尝试这个hasElement()检查。(不确定我是否正确使用了它-我正在尝试和调试) 基本上:我想检查是否已经存在元素,保存是非法的,我不会调

  • 问题内容: 我试图在Netbeans中重构一个大型程序,但我有点迷茫。我从来没有非常模块化,但是现在通过实际学习如何做到这一点来尝试纠正这种情况,并在将来纠正这种情况。不幸的是,我在将某些教程翻译成我的程序时遇到了麻烦。所以我希望这里有人可以帮忙。目前,我正在尝试分解一部分采用特定格式的文件并制成表格的代码。我知道我需要创建一个类并使用它来创建表对象,但是我不确定如何做。我有一个主文件,用于获取文

  • 我对编程很陌生,所以这个问题看起来很傻。下面提到的方法有一个作为int数组的返回类型。当我们不抛出任何未经检查的异常时,它会抛出一个我理解的错误。但是为什么包含一个未检查的异常会删除那个错误呢?它仍然没有任何返回语句,不是吗?

  • 问题内容: 如果catch和finally块都抛出异常会怎样? 问题答案: 当该块引发异常时,它将有效地隐藏从该块引发的异常,并将最终引发该异常。因此,重要的是要么在捕获时记录异常,要么确保finally块本身不会引发异常,否则,您将得到被扼杀且从未见过的异常​​。