是啥导致 java.lang.***Error

Posted

技术标签:

【中文标题】是啥导致 java.lang.***Error【英文标题】:What causes a java.lang.***Error是什么导致 java.lang.***Error 【发布时间】:2011-03-12 23:31:59 【问题描述】:

什么会导致java.lang.***Error?我得到的堆栈打印输出根本不是很深(只有 5 个方法)。

【问题讨论】:

这篇文章可能会有所帮助:***.com/questions/860550/… 【参考方案1】:

在我的情况下,我必须覆盖子类中的 equals 和 hashcode 类方法

    @Override
public boolean equals(Object o) 
    if (this == o) return true;
    if (!(o instanceof MyClass)) return false;
    return id != null && id.equals(((MyClass) o).getId());


@Override
public int hashCode() 
    return getClass().hashCode();

参考这里:vladmihalcea article

【讨论】:

【参考方案2】:

在我的例子中 toString 导致实体类中的异常检查您的系统日志它将帮助您解决异常

【讨论】:

【参考方案3】:

我遇到了同样的问题

角色.java

 @ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY,cascade = CascadeType.ALL)
 Set<BusinessUnitMaster> businessUnits =new HashSet<>();

BusinessUnitMaster.java

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(
        name = "BusinessUnitRoles",
        joinColumns = @JoinColumn(name = "unit_id", referencedColumnName = "record_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "record_id")
)
private Set<Role> roles=new HashSet<>();

问题是当你创建 BusinessUnitMaster 和 Role 您必须为双方保存对象 对于 RoleService.java

roleRepository.save(role);

对于 BusinessUnitMasterService.java

businessUnitMasterRepository.save(businessUnitMaster);

【讨论】:

【参考方案4】:

Hibernate 用户解析数据时的解决方案:

我遇到此错误是因为我正在使用 jackson 将映射在两侧 @OneToMany@ManyToOne 的对象列表解析为 json,从而导致无限循环。

如果您遇到同样的情况,您可以使用@JsonManagedReference@JsonBackReference 注释来解决此问题。

API 定义:

JsonManagedReference (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html):

注解用于表明被注解的属性是双向的一部分 领域之间的联系;并且它的角色是“父母”(或“转发”) 关联。值类型(类)的属性必须有一个单一的兼容 用 JsonBackReference 注释的属性。联动是这样处理的 用这个注解注解的属性被正常处理 (正常序列化,反序列化无特殊处理);它是 需要特殊处理的匹配反向引用

JsonBackReference: (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html):

用于指示关联属性是一部分的注释 字段之间的双向联动;并且它的角色是“孩子”(或 “返回”)链接。属性的值类型必须是 bean:不能是 集合、映射、数组或枚举。处理链接使得 使用此注解注解的属性未序列化;和 在反序列化期间,其值设置为具有 “托管”(转发)链接。

例子:

Owner.java:

@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;

Car.java:

@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;

另一种解决方案是使用 @JsonIgnore,它只会将字段设置为 null。

【讨论】:

【参考方案5】:

什么是java.lang.***Error

抛出错误 java.lang.***Error 表明应用程序的堆栈已耗尽,这是由于深度递归,即您的程序/脚本递归太深。

详情

***Error 扩展了 VirtualMachineError 类,表明 JVM 已经或已经耗尽资源,无法进一步操作。 VirtualMachineError 扩展了 Error 类,用于指示应用程序不应捕获的严重问题。方法可能不会在其 throw 子句中声明此类错误,因为这些错误是不希望发生的异常情况。

一个例子

Minimal, Complete, and Verifiable Example

package demo;

public class ***ErrorExample 

    public static void main(String[] args) 
    
        ***ErrorExample.recursivePrint(1);
    

    public static void recursivePrint(int num) 
        System.out.println("Number: " + num);

        if(num == 0)
            return;
        else
            recursivePrint(++num);
    


控制台输出

Number: 1
Number: 2
.
.
.
Number: 8645
Number: 8646
Number: 8647Exception in thread "main" java.lang.***Error
    at java.io.FileOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.flush(Unknown Source)
    at java.io.PrintStream.write(Unknown Source)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
    at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
    at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
    at java.io.PrintStream.newLine(Unknown Source)
    at java.io.PrintStream.println(Unknown Source)
    at demo.***ErrorExample.recursivePrint(***ErrorExample.java:11)
    at demo.***ErrorExample.recursivePrint(***ErrorExample.java:16)
    .
    .
    .
    at demo.***ErrorExample.recursivePrint(***ErrorExample.java:16)

说明

当 Java 应用程序调用函数调用时,会在 调用堆栈 上分配一个堆栈帧stack frame 包含被调用方法的参数、它的本地参数和方法的返回地址。返回地址表示被调用的方法返回后程序继续执行的执行点。如果没有空间用于新的堆栈帧,则 ***Error 由 Java 虚拟机 (JVM) 抛出。

可能耗尽 Java 应用程序堆栈的最常见情况是递归。在递归中,方法在执行期间调用自身。 Recursion 最强大的通用编程技术之一,但必须谨慎使用,以避免 ***Error

参考文献

Java Doc ***Error

【讨论】:

【参考方案6】:

当线程堆栈的大小继续增长直到达到最大限制时,可能会发生堆栈溢出异常。

调整堆栈大小(Xss 和 Xmso)选项...

我建议您查看此链接: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 ***Error 有很多可能的原因,您可以在链接中看到......

【讨论】:

一般不接受仅链接的答案;链接中断,这将使答案完全无效。请提供一些上下文、代码和答案解释,而不仅仅是一个链接。【参考方案7】:

就我而言,我有两个活动。在第二个活动中,我忘记将 super 放在 onCreate 方法上。

super.onCreate(savedInstanceState);

【讨论】:

即使有可能提出***Error,我也不认为它正在回答这个问题。我认为一个正确的答案应该要么列出除使用过多递归之外的其他方法来获取此异常,要么说除了手动抛出之外绝对没有其他方法可以获取此类异常。【参考方案8】:

当 Java 应用程序调用函数调用时,会在调用堆栈上分配一个堆栈帧。堆栈帧包含被调用方法的参数、其本地参数和方法的返回地址。

返回地址表示被调用方法返回后程序继续执行的执行点。如果没有空间用于新的堆栈帧,则 Java 虚拟机 (JVM) 会抛出 ***Error。

可能耗尽 Java 应用程序堆栈的最常见情况是递归。

请看一下

How to solve ***Error

【讨论】:

【参考方案9】:

我用 hibernate 创建了一个程序,其中我创建了两个 POJO 类,它们都具有彼此的对象作为数据成员。在 main 方法中我尝试将它们保存在数据库中时,我也遇到了这个错误。

发生这种情况是因为两个类相互引用,因此创建了导致此错误的循环。

因此,请检查您的程序中是否存在任何此类关系。

【讨论】:

【参考方案10】:

检查任何对方法的递归调用。主要是在递归调用方法时引起的。一个简单的例子是

public static void main(String... args) 
    Main main = new Main();

    main.testMethod(1);


public void testMethod(int i) 
    testMethod(i);

    System.out.println(i);

这里是 System.out.println(i);调用testMethod时会重复压栈。

【讨论】:

我认为你是对的。但是它的解决方案是什么。因为我们正在制作一种方法来回避它,这意味着我们需要它。我们不想改变方法。那么如何解决这个错误呢? 或者你进入了一个无限循环! @yalematta,任何递归方法都应该有退出的条件。因此,请检查您的递归方法是否正确实现并根据某些条件完成。 @AjaySharma 我们需要设计我们的系统以适应我们分配给 JVM 的可用内存边界。如果系统因以下错误而表现不佳,那么我们需要检查我们的代码库。【参考方案11】:

实际上导致 java.lang.***Error 的原因通常是无意的递归。对我来说,通常是我打算为覆盖的方法调用超级方法。比如本例:

public class Vehicle 
    public void accelerate(float acceleration, float maxVelocity) 
        // set the acceleration
    


public class SpaceShip extends Vehicle 
    @Override
    public void accelerate(float acceleration, float maxVelocity) 
        // update the flux capacitor and call super.accelerate
        // oops meant to call super.accelerate(acceleration, maxVelocity);
        // but accidentally wrote this instead. A *** is in our future.
        this.accelerate(acceleration, maxVelocity); 
    

首先,了解调用函数时幕后发生的事情很有用。调用方法的参数和地址被压入堆栈(参见http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management),以便被调用方法可以访问参数,并且当被调用方法完成时,调用后可以继续执行。但是由于我们递归调用 this.accelerate(acceleration, maxVelocity) (当方法调用自身时,递归是松散的。有关更多信息,请参阅http://en.wikipedia.org/wiki/Recursion_(computer_science))我们处于一种称为无限递归的情况,我们不断堆积参数和返回地址在调用堆栈上。由于调用堆栈的大小是有限的,我们最终会耗尽空间。调用堆栈上的空间不足称为溢出。这是因为我们试图使用比我们拥有的更多的堆栈空间,并且数据实际上溢出了堆栈。在 Java 编程语言中,这会导致运行时异常 java.lang.*** 并立即停止程序。

上面的例子有些简化(尽管它发生在我身上的次数比我想承认的要多。)同样的事情可能会以更复杂的方式发生,这使得追踪起来有点困难。但是,一般来说,一旦发生 ***,通常很容易解决。

理论上,没有递归也可能发生堆栈溢出,但在实践中,这似乎是相当罕见的事件。

【讨论】:

【参考方案12】:

JVM 的一个(可选)参数是堆栈大小。这是-Xss。我不知道默认值是多少,但是如果堆栈上的东西总量超过了这个值,你就会得到那个错误。

通常,无限递归是造成这种情况的原因,但如果您看到这种情况,您的堆栈跟踪将超过 5 帧。

尝试添加一个 -Xss 参数(或增加一个的值),看看这是否会消失。

【讨论】:

以上是关于是啥导致 java.lang.***Error的主要内容,如果未能解决你的问题,请参考以下文章

是啥导致 java.lang.ArrayIndexOutOfBoundsException 以及如何防止它?

是啥导致 java.lang.ArrayIndexOutOfBoundsException 以及如何防止它?

是啥导致 java.lang.ArrayIndexOutOfBoundsException 以及如何防止它?

是啥导致 java.lang.ArrayIndexOutOfBoundsException 以及如何防止它?

是啥导致“java.lang.IllegalStateException:Bean 名称‘command’的 BindingResult 和普通目标对象都不能用作请求属性”?

java.lang包中的lang是啥意思?