=====文章目录=====
OutOfMemoryError演示
第一种,StackOverflowError
栈满会抛出该错误。无限递归就会导致StackOverflowError,是java.lang.Throwable
→java.lang.Error
→java.lang.VirtualMachineError
下的错误。
代码
package jvm;
public class StackOverflowErrorDemo {
public static void main(String[] args) {
stackOverflowError();
}
private static void stackOverflowError() {
stackOverflowError();
}
}
输出
Exception in thread "main" java.lang.StackOverflowError
at jvm.StackOverflowErrorDemo.stackOverflowError(StackOverflowErrorDemo.java:9)
at jvm.StackOverflowErrorDemo.stackOverflowError(StackOverflowErrorDemo.java:9)
第二种,Java heap space
栈满会抛出该错误。
在 IDEA菜单栏---Run---Edit Configurations ---VM options
填写以下参数
-Xms10m -Xmx10m
最后,右键run运行。
代码
package jvm;
import java.util.Random;
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
public class JavaHeapSpaceDemo {
public static void main(String[] args) {
String str = "adf";
while (true) {
str += str + new Random().nextInt(1111111) + new Random().nextInt(222222);
str.intern();
}
}
}
输出
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
at java.lang.StringBuilder.append(StringBuilder.java:208)
at jvm.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:10)
GC overhead limit exceeded
GC回收时间过长时会地出 outofMemroyError。过长的定义是,则过98%的时间用来做GC并且回收了不到2%的堆内
连续多次GC都只回收了不到2%的极端情况下才会抛出。假如不抛出 GC overhead limit错误会发生什么情况呢?
那就是GC清理的这么点内存很块会再次填满,道使GC再次执行,这样就形成恶性循坏
CPU使用率一直是100%,GC却没有任何成果
代码
package jvm;
import java.util.ArrayList;
import java.util.List;
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
public class GCOverheadDemo {
public static void main(String[] args) {
int i = 0;
List<String> list = new ArrayList<>();
try {
while (true) {
list.add(String.valueOf(++i).intern());
}
} catch (Exception e) {
System.out.println("************i" + i);
e.printStackTrace();
throw e;
}
}
}
输出
详细情况
[GC (Allocation Failure) [PSYoungGen: 2035K->496K(2560K)] 2035K->1020K(9728K), 0.0016816 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 2544K->505K(2560K)] 3068K->2701K(9728K), 0.0024345 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 2553K->512K(2560K)] 4749K->4593K(9728K), 0.0030155 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 2560K->496K(2560K)] 6641K->6650K(9728K), 0.0037446 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 496K->0K(2560K)] [ParOldGen: 6154K->6218K(7168K)] 6650K->6218K(9728K), [Metaspace: 3214K->3214K(1056768K)], 0.0721823 secs] [Times: user=0.27 sys=0.00, real=0.07 secs]
[Full GC (Ergonomics) [PSYoungGen: 2048K->824K(2560K)] [ParOldGen: 6218K->7020K(7168K)] 8266K->7845K(9728K), [Metaspace: 3214K->3214K(1056768K)], 0.0489867 secs] [Times: user=0.23 sys=0.00, real=0.05 secs]
...
...
[Full GC (Ergonomics) [PSYoungGen: 2047K->2047K(2560K)] [ParOldGen: 7061K->7061K(7168K)] 9109K->9109K(9728K), [Metaspace: 3218K->3218K(1056768K)], 0.0330914 secs] [Times: user=0.13 sys=0.00, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 2047K->2047K(2560K)] [ParOldGen: 7063K->7063K(7168K)] 9111K->9111K(9728K), [Metaspace: 3218K->3218K(1056768K)], 0.0327293 secs] [Times: user=0.08 sys=0.00, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 2047K->2047K(2560K)] [ParOldGen: 7065K->7065K(7168K)] 9113K->9113K(9728K), [Metaspace: 3218K->3218K(1056768K)], 0.0278034 secs] [Times: user=0.20 sys=0.00, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 2047K->2047K(2560K)] [ParOldGen: 7067K->7067K(7168K)] 9115K->9115K(9728K), [Metaspace: 3218K->3218K(1056768K)], 0.0292778 secs] [Times: user=0.22 sys=0.00, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 2047K->0K(2560K)] [ParOldGen: 7092K->614K(7168K)] 9140K->614K(9728K), [Metaspace: 3249K->3249K(1056768K)], 0.0072447 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 2560K, used 166K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 8% used [0x00000000ffd00000,0x00000000ffd29ad0,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 7168K, used 614K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
object space 7168K, 8% used [0x00000000ff600000,0x00000000ff699b60,0x00000000ffd00000)
Metaspace used 3325K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 359K, capacity 388K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.Integer.toString(Integer.java:403)
at java.lang.String.valueOf(String.java:3099)
at jvm.GCOverheadDemo.main(GCOverheadDemo.java:13)
Direct buffer memory
写NIO程序经常使用 ByteBuffer来读或者写入数据,这是一种基于通道( Channel)与缓冲区( Buffer)的 I/O方式,
它可以使用 Native函数库直接分配堆外内存,然后通过一个存在Java里面 DirectByteBuffer0象作为这块内存的引用进行操作
这样能在一些场景中显著提高性能,因为避免了在Jva和 Native堆中来回复制数据。
ByteBuffer.allocate( capability)
第一种方式是分配W内存,属GC管辖范国,由于需要贝所以速度相较慢
ByteBuffer.allocateDirect( capability)
第一种方式是分配OS本地内存,不属GC管接范围,由于下需要内存拷贝所纵速度相对较快
但如果不断分配本地内存,推内存很少使用,那么W就不需要行GC, DirectByte Buffer对象们就不会被回收,
时候内存充足,但本地内存可能已经使用光了,再尝试分配本地内存就会出现0ut0 mEmory Error,那程序就直接 崩溃了。
代码
package jvm;
import java.nio.ByteBuffer;
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
public class DirectBufferMemoryDemo {
public static void main(String[] args) {
System.out.println("配置的maxDirectMemory: "
+ (sun.misc.VM.maxDirectMemory() / (double) 1024 / 1024) + "MB");
try {
Thread.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}
OOM—unable to create new native thread
在高并发应用场景时,如果创建超过了系统默认的最大线程数,就会抛出该异常。Linux单个进程默认不能超过1024个线程。解决方法要么降低程序线程数,要么修改系统最大线程数vim /etc/security/limits.d/90-nproc.conf
。
package jvm;
public class UnableCreateNewThreadDemo {
public static void main(String[] args) {
for (int i = 0; ; i++) {
System.out.println("***********" + i);
new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "" + i).start();
}
}
}
输出
***********0
***********1
...
...
***********47842
***********47843
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at jvm.UnableCreateNewThreadDemo.main(UnableCreateNewThreadDemo.java:13)
OOM—Metaspace
元空间满了就会抛出这个异常。
代码
package jvm;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* java 8及之后版本使用Metaspace来代替永久代
* -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m
*
* 永久代(java8使用Metaspace)存放的信息:
* 虚拟机加载的类信息
* 常量池
* 静态变量
* 即时编译后的代
*
* 模拟Metaspace空间溢出,我们不断生成类往空间灌,类占据的空间总是会超时Metaspace指定的空间大小的
*/
public class MetaspaceOOMTest {
static class OOMTest {
}
public static void main(String[] args) {
int i = 0;
try {
while (true) {
i++;
// 使用CGLIB生成代理:
// 1.创建核心类:
Enhancer enhancer = new Enhancer();
// 2.为其设置父类:
enhancer.setSuperclass(OOMTest.class);
// 3.设置回调:
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return methodProxy.invokeSuper(object, args);
}
});
enhancer.create();
}
} catch (Throwable e) {
System.out.println("**********多少次后发生了异常: " + i);
e.printStackTrace();
}
}
}
输出
"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" ...
Error occurred during initialization of VM
MaxMetaspaceSize is too small.
报的错误有点不一样,正常来说应该是报这个的,可能是版本不一样吧。