Làm thế nào để xử lý lỗi java.lang.StackOverflowError là gì?

Tôi tin rằng khi các bạn xử dụng vòng lặp hoặc đã dùng qua framework JPA, Hibernate thì các bạn đã mắc phải lỗi java.lang.StackOverflowError này rồi. Trong bài viết này, tôi sẽ giới thiệu đến các bạn nguyên nhân, cách khắc phục của lỗi java.lang.StackOverflowError như thế nào. Let’s go!

Nguyên nhân lỗi java.lang.StackOverflowError  là gì?

Lỗi java.lang.StackOverflowError được sinh ra khi chạy chương trình (runtime) thì chắc chắn một điều rằng java.lang.StackOverflowError nó sẽ kế thừa từ lớp RuntimeException. Đây làm một lỗi rất nghiêm trọng khi xảy ra cho hệ thống.

Lỗi java.lang.StackOverflowError xảy ra khi  stack đạt đến giới hạn tối đa.

Thường thì có 3 nguyên nhân chính xảy ra lỗi java.lang.StackOverflowError:

  1. Khi ta sử dụng đệ quy nhưng không có điều kiện kết thúc.
  2. Mối quan hệ giữa các lớp – Nếu một lớp Akhởi tạo một đối tượng của lớp B, thì đối tượng này sẽ khởi tạo một đối tượng của lớp A. Đây có thể coi là một dạng của đệ quy.
  3. Các ứng dụng sử dụng nhiều bộ nhớ – Các ứng dụng dựa trên các đối tượng nặng về tài nguyên như tài liệu XML, các lớp GUI hoặc java2D dẫn đến stack overload.

Cách khắc phục java.lang.StackOverflowError?

Để khắc phục và hạn chế xảy ra lỗi java.lang.StackOverflowError ta nên để ý xử lý điều kiện để chương trình dừng lại khi dụng vòng lặp, đệ quy hay ta tăng kích thước -Xss như:

-Xss4m

Ví dụ về java.lang.StackOverflowError

public class StackOverflowErrorExample {
    public void show(int number) {
        System.out.println(number);
        print(number);
    }

    public static void main(String[] args) {
        StackOverflowErrorExample s = new StackOverflowErrorExample();
        s.show(0);
    }
}

Ví dụ trên sẽ xảy ra ngoại lệ ngoài ý muốn khi phương thức show() luôn luôn call lại method của chính nó mà không bao giờ có một điều kiện để dừng, nên chương trình sẽ throw ra lỗi java.lang.StackOverflowError.

Dưới đây là console log errors:

Exception in thread "main" java.lang.StackOverflowError
    at java.base/sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:564)
    at java.base/java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:585)
    at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:301)
    at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:290)
    at java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:131)
    at java.base/java.io.OutputStreamWriter.write(OutputStreamWriter.java:208)
    at java.base/java.io.BufferedWriter.flushBuffer(BufferedWriter.java:120)
    at java.base/java.io.PrintStream.writeln(PrintStream.java:722)
    at java.base/java.io.PrintStream.println(PrintStream.java:938)
    at StackOverflowErrorExample.print(StackOverflowErrorExample.java:3)
    at StackOverflowErrorExample.print(StackOverflowErrorExample.java:4)
    at StackOverflowErrorExample.print(StackOverflowErrorExample.java:4)
    at StackOverflowErrorExample.print(StackOverflowErrorExample.java:4)
    at StackOverflowErrorExample.print(StackOverflowErrorExample.java:4)

Bonus

Một ví dụ nữa khi các bạn sử dụng quan hệ giữa relationship giữa các object trong Hibernate, JPA như ManyToOne, OneToMany, ManyToMany thì hãy để ý rằng việc sử dụng trên nên chuyển đổi annotation lombok @Data sang các annotation như: @Getter, @Setter. Vì bản thân @Data đã chứa các thành phần @Setter,@Getter, @ToString và @EqualsAndHashCode. Việc sử dụng @Data nó sẽ sử dụng @ToString để show thông tin của class A đến Class B và ngược lại dẫn đến việc không có điểm dừng.

Hy vọng bài viết sẽ giúp ích cho các bạn khi mắc phải lỗi : java.lang.StackOverflowError!

Happy Coding! 😋