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];
}
}
输出:
Note: If you run this code you will get java.lang.StackOverflowError. We can avoid it by adding proper termination condition if we add termination condition in factorial function before return statement. Below termination condition remove error as follows:
if(n==0)
return 0;
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。