JVM--内存结构--本地方法栈&堆
本地方法栈
- 指不是由Java代码编写的代码,如C和C++和操作系统直接打交道
- 本地方法有很多,如Object类中的clone方法,属于native方法
作用
- 给本地方法的执行提供内存空间
Heep 堆
- 通过 new 关键字,创建对象都会使用堆内存
特点
- 它是线程共享的,堆中对象都需要考虑线程安全的问题
- 有垃圾回收机制
堆内存溢出
演示代码:
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 堆内存诊断
- jps 工具
- 查看当前系统中有哪些 java 进程
- jmap 工具–只能查询某个时刻
- 查看堆内存占用情况 jmap - heap 进程id
- 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>