而1.8后,Hotspot虚拟机已经移除了永久代,使用了元空间代替。
正确配置限制-XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m
对于JVM里面的内存需要在启动时进行限制,包括我们熟悉的堆内存,也要包括直接内存和元生区,这是保证线上服务正常运行最后的兜底
一般来说内存溢出主要分为以下几类:
堆溢出(java.lang.OutOfMemoryError: Java heap space)
栈深度不够( java.lang.StackOverflowError)
栈线程数不够(java.lang.OutOfMemoryError: unable to create new native thread)
元空间溢出(java.lang.OutOfMemoryError: Metaspace)
pmap - report memory map of a process(查看进程的内存映像信息)
pmap命令用于报告进程的内存映射关系,是Linux调试及运维一个很好的工具。
pmap -x pid 如果需要排序 | sort -n -k3**
pmap -x pid | sort -k 3 -n -r | head -n 10
设置初始堆大小和最大堆大小均为4GB。这可以避免JVM在运行过程中动态调整堆大小,提高性能稳定性。
查看jvm参数
jinfo -flags 27
1.JVM 向操作系统申请内存,JVM 第一步就是通过配置参数或者默认配置参数向操作系统申请内存空间,根据内存大小找到具体的内存分配表,然后把内存段的起始地址和终止地址分配给 JVM,接下来 JVM 就进行内部分配。
2.JVM 获得内存空间后,会根据配置参数分配堆、栈以及方法区的内存大小
3.class 文件加载、验证、准备以及解析,其中准备阶段会为类的静态变量分配内存,初始化为系统的初始值
4.完成上一个步骤后,将会进行最后一个初始化阶段。在这个阶段中,JVM 首先会执行构造器<client>()方法,编译器会在.java 文件被编译成.class 文件时,收集所有类的初始化代码,包括静态变量赋值语句、静态代码块、静态方法,收集在一起成为<client>()方法。
5.执行方法。启动 main 线程,执行 main 方法,开始执行第一行代码。此时堆内存中会创建一个 student 对象,对象引用 student 就存放在栈中。
6.此时再次创建一个 JVMCase 对象,调用 sayHello 非静态方法,sayHello 方法属于对象 JVMCase,此时 sayHello 方法入栈,并通过栈中的 student 引用调用堆中的 Student 对象;之后,调用静态方法 print,print 静态方法属于 JVMCase 类,是从静态方法中获取,之后放入到栈中,也是通过 student 引用调用堆中的 student 对象。