JVM(完成度95%,不断更新) (15)

Netty + NIO:这是由于NIO引起的
写NIO程序的时候经常会使用ByteBuffer来读取或写入数据,这是一种基于通道(Channel) 与 缓冲区(Buffer)的I/O方式,它可以使用Native 函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
ByteBuffer.allocate(capability):第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢
ByteBuffer.allocteDirect(capability):第二种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存的拷贝,所以速度相对较快
但如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象就不会被回收,这时候怼内存充足,但本地内存可能已经使用光了,再次尝试分配本地内存就会出现OutOfMemoryError,那么程序就奔溃了。
一句话说:本地内存不足,但是堆内存充足的时候,就会出现这个问题

为了更快的达到效果,我们首先需要设置JVM启动参数 -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m // 只设置了5M的物理内存使用,但是却分配 6M的空间 ByteBuffer bb = ByteBuffer.allocateDirect(6 * 1024 * 1024); -------------------------- 配置的maxDirectMemory:5.0MB [GC (System.gc()) [PSYoungGen: 2030K->488K(2560K)] 2030K->796K(9728K), 0.0008326 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (System.gc()) [PSYoungGen: 488K->0K(2560K)] [ParOldGen: 308K->712K(7168K)] 796K->712K(9728K), [Metaspace: 3512K->3512K(1056768K)], 0.0052052 secs] [Times: user=0.09 sys=0.00, real=0.00 secs] Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory at java.nio.Bits.reserveMemory(Bits.java:693) at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311) at com.moxi.interview.study.oom.DIrectBufferMemoryDemo.main(DIrectBufferMemoryDemo.java:19)

unable to create new native thread

不能够创建更多的新的线程了,也就是说创建线程的上限达到了
在高并发场景的时候,会应用到
高并发请求服务器时,经常会出现如下异常java.lang.OutOfMemoryError:unable to create new native thread,准确说该native thread异常与对应的平台有关


导致原因:

应用创建了太多线程,一个应用进程创建多个线程,超过系统承载极限

服务器并不允许你的应用程序创建这么多线程,linux系统默认运行单个进程可以创建的线程为1024个(除去系统占用,实际在900左右,当然root用户没有上限),如果应用创建超过这个数量,就会报 java.lang.OutOfMemoryError:unable to create new native thread


解决方法:

想办法降低你应用程序创建线程的数量,分析应用是否真的需要创建这么多线程,如果不是,改代码将线程数降到最低

对于有的应用,确实需要创建很多线程,远超过linux系统默认1024个线程限制,可以通过修改linux服务器配置,扩大linux默认限制


```java public class UnableCreateNewThreadDemo { public static void main(String[] args) { for (int i = 0; ; i++) { System.out.println("************** i = " + i); new Thread(() -> { try { TimeUnit.SECONDS.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { e.printStackTrace(); } }, String.valueOf(i)).start(); } } }

这个时候,就会出现下列的错误,线程数大概在 900多个
Exception in thread "main" java.lang.OutOfMemoryError: unable to cerate new native thread

如何查看线程数 ```shell ulimit -u

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwsdps.html