📜  Java的堆和堆栈内存错误

📅  最后修改于: 2022-05-13 01:54:42.377000             🧑  作者: Mango

Java的堆和堆栈内存错误

在Java内存分配是由Java虚拟机在Java中进行管理。它将内存分为栈内存和堆内存,如下图所示:

Java的堆栈内存

它是临时内存分配,其中局部变量、引用变量在调用它们的方法时分配内存。它包含对存储在堆中的对象的引用。方法执行后,包含这些变量的内存被清除。我们可以按照后进先出的顺序访问这个内存。分配和释放比堆内存快。它更安全,因为数据只能由线程所有者访问。如果堆栈内存已满,则 JVM 会抛出 StackOverflowException。

插图:



// Java Program to Illustrate Stack Memory  

// Importing required I/O classes 
import java.io.*;

// Main class 
class GFG {

    // Main driver method 
    public static void main (String[] args) {

        // Creating an integer array 
        int a [] = new int[5];  
    }
}

上例图解说明

在上图中,我们可以最终感知上述显示的媒体并得出以下几点

  • 'a' 是存储在堆栈中的数组类型变量。
  • new 关键字用于在堆中分配内存。
  • 5 是数组的大小。

堆栈内存错误

每当我们调用一个方法时,它在执行后都会离开堆栈内存。如果您的方法保留在堆栈中,那么堆栈将已满,如果堆栈已满,我们将无法推送,如果我们这样做,我们将收到错误Java.lang.StackOverflowError,JVM 将抛出该错误。当您调用一个方法并且堆栈中没有剩余空间时会抛出它。在大多数情况下,当我们在没有任何适当终止条件的情况下递归调用方法时会抛出它。我们可以通过确保方法在正确终止的情况下执行来避免它。

达到一定程度后,堆栈将已满

让我们举一个计算数字阶乘的示例来说明这一点。

Java
// Java Program to Illustrate Stack Memory Error
// Factorial function without termination condition
// will cause StackOverflow error
 
// Importing I/O classes
import java.io.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main (String[] args) {
 
        // Declaring a custom number whose factorial is to be computed
        int n = 5;
 
        // Print and display the factorial
        System.out.println(factorial(n));
    }
 
    // Method
    // To calculate factorial
    static int factorial(int n) {
 
        // Note: There is no termination condition
 
        // Calling recursively to compute factorial of a number
        return n * factorial(n - 1);
    }
}


Java
// Java Program to Illustrate Execution in Heap Memory
 
// Importing input output classes
import java.io.*;
 
// Main class
class GFG {
 
    // Static class
    static class Student {
 
        int roll_no;
 
        // The reference variable of String argument name
        // which points to the actual string from string
        // pool in heap memory
        String name;
 
        // Constructor of this static class
        Student(int roll_no, String name)
        {
 
            // This keyword refers to current instance
            this.roll_no = roll_no;
            this.name = name;
        }
    }
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Primitive roll no value directly stored in stack
        // memory
        int roll_no = 1;
        // Primitive name value directly stored in stack
        // memory
        String name = "Jack";
 
        // Creating reference variable of Student class type
        // created in a stack memory which will point to
        // the object in heap memory
        // New object created in heap memory
        Student st = new Student(roll_no, name);
 
        // Print and display the student name and roll
        // number
        System.out.println("Student name -> " + st.name);
        System.out.println("Student roll no. -> "
                           + st.roll_no);
    }
}


Java
// Java Program to Illustrate OutOfMemoryError
// in Heap Space
 
// Importing input output classes
import java.io.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating an array whose size is havoc
        Long a[] = new Long[100000 * 10000];
    }
}


输出:

Java的堆内存

Java的堆内存用于为对象和 JRE(Java运行时环境)类分配内存。创建对象时,它总是在堆中创建,对对象的引用存储在堆栈内存中。它作为堆栈并不安全,因为它可以全局访问。访问此内存相对比堆栈内存慢。它需要一个垃圾收集器来删除未使用的对象。如果堆已满,JVM 会抛出Java.lang.OutOfMemoryError 。它不像堆栈那样是线程安全的。

例子

Java

// Java Program to Illustrate Execution in Heap Memory
 
// Importing input output classes
import java.io.*;
 
// Main class
class GFG {
 
    // Static class
    static class Student {
 
        int roll_no;
 
        // The reference variable of String argument name
        // which points to the actual string from string
        // pool in heap memory
        String name;
 
        // Constructor of this static class
        Student(int roll_no, String name)
        {
 
            // This keyword refers to current instance
            this.roll_no = roll_no;
            this.name = name;
        }
    }
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Primitive roll no value directly stored in stack
        // memory
        int roll_no = 1;
        // Primitive name value directly stored in stack
        // memory
        String name = "Jack";
 
        // Creating reference variable of Student class type
        // created in a stack memory which will point to
        // the object in heap memory
        // New object created in heap memory
        Student st = new Student(roll_no, name);
 
        // Print and display the student name and roll
        // number
        System.out.println("Student name -> " + st.name);
        System.out.println("Student roll no. -> "
                           + st.roll_no);
    }
}
输出
Student name -> Jack
Student roll no. -> 1

堆内存错误

现在也适合讨论Java的堆内存错误。因此,当我们在堆内存中创建大量新对象并且没有空间留给新对象时,确实会发生这种情况,然后 JVM 将抛出Java.lang.OutOfMemoryError 。垃圾收集器删除了没有引用的对象,但不能删除有引用的对象。可以通过删除对不需要的对象的引用来避免这种情况。

例子:

Java

// Java Program to Illustrate OutOfMemoryError
// in Heap Space
 
// Importing input output classes
import java.io.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating an array whose size is havoc
        Long a[] = new Long[100000 * 10000];
    }
}

输出:

输出说明:在上面的例子中,尝试初始化一个非常大的Long数组,而Java堆不足以分配这个数组,在Java堆空间抛出Java .lang.OutOfMemoryError。