本地方法栈

  • 指不是由Java代码编写的代码,如C和C++和操作系统直接打交道
  • 本地方法有很多,如Object类中的clone方法,属于native方法

作用

  • 给本地方法的执行提供内存空间

Heep 堆

  • 是JVM管理中最大的一块内存
  • 通过 new 关键字,创建对象都会使用堆内存,唯一的目的就是存放对象实例

特点

  • 它是线程共享的,堆中对象都需要考虑线程安全的问题
  • 有垃圾回收机制,是GC主要管理的区域

堆内存溢出

演示代码:

 public static void main(String[] args) {
        int i = 0;
        try {
            List<String> list = new ArrayList<>();
            String a = "hello";
            while (true) {
                list.add(a); // hello, hellohello, hellohellohellohello ...
                a = a + a;  // hellohellohellohello
                i++;
            }
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println(i);
        }
    }

结果:

java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.Arrays.copyOf(Arrays.java:3746)
at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:227)
at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:593)
at java.base/java.lang.StringBuilder.append(StringBuilder.java:172)
at cn.xzzz2020.controller.demo.main(demo.java:33)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
26

可能因为电脑内存的太大,所以堆内存溢出的错误暴露会比较久,<mark>所以想要排除堆内存的问题,可以将堆内存设置的小一点</mark>

4.3 堆内存诊断

  1. jps 工具
  • 查看当前系统中有哪些 java 进程
  1. jmap 工具–只能查询某个时刻
  • 查看堆内存占用情况 jmap - heap 进程id
  1. jconsole 工具
  • 图形界面的,多功能的监测工具(线程、cpu),可以连续监测

代码演示:

/** * 演示堆内存 */
public class Demo1_4 {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("1...");
        Thread.sleep(30000);
        byte[] array = new byte[1024 * 1024 * 10]; // 10 Mb
        System.out.println("2...");
        Thread.sleep(20000);
        array = null;
        System.gc();
        System.out.println("3...");
        Thread.sleep(1000000L);
    }
}

案例:垃圾回收后,内存占用仍然很高

代码

/** * 演示查看对象个数 堆转储 dump */
public class demo {

    public static void main(String[] args) throws InterruptedException {
        List<Student> students = new ArrayList<>();
        for (int i = 0; i < 200; i++) {
            students.add(new Student());
// Student student = new Student();
        }
        Thread.sleep(1000000000L);
    }
}
class Student {
    private byte[] big = new byte[1024*1024];
}

<mark>利用jvisualvm命令中堆转储 dump排查错误</mark>