B02、GC日志分析-案例演示-6.4

1、案例一:堆溢出演示

1.1、简单springboot项目创建

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.5</version><relativePath/></parent><groupId>blnp.net.cn</groupId><artifactId>demo-items</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>2.2.5.RELEASE</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.0</version></dependency></dependencies>
</project>

        完整代码,可以通过下载文章顶部的《案例一:堆溢出演示代码》,进行演示复现。

1.2、配置项目启动参数

-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause -XX:MetaspaceSize=64m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=system/heap/heapdump.hprof -Xms50m -Xmx50m -Xloggc:system/log/gc-oomHeap.log

特别说明:这里有几个注意事项需要留意下,我这边使用的JDK版本是(1.8.0_131)。堆大小设置建议直接设置为 50m,较为容易复现(java.lang.OutOfMemoryError: Java heap space)错误。此外也要特别注意参数的大小写问题,如果因为部分单词小写了,也是无法启动并且会输出以下异常:

Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
Unrecognized VM option 'PrintGcDateStamps'
Did you mean '(+/-)PrintGCDateStamps'?Process finished with exit code 1

        项目启动成功后,通过访问该接口(http://localhost:8080/add)进行异常触发。

        与此同时工程根目录下的(system)目录将会生成以下几个文件:

  1. 这里的目录需要手动进行创建
  2. 关于 .hprof 文件,如果目录已经有同名的文件,后续发生异常时将不会进行覆盖输出
  3. 对于 .log 则相反会持续不断的追加输出

1.3、分析生成文件

1、GCeasy 在线分析

        通过访问GCeasy,将上述代码生成的 gc-oomHeap.log 文件上传至网站并执行分析操作。

        如果程序生成GC日志文件不是很大的会,不需要多久就会生成对应的分析报告。分析报告有两种,一个是直接在该站点查看在线分析报告;另一个则是通过下载生成的 PDF分析报告。

在线分析报告:

  • Ergonomics:表示jvm在自适应调优
  • Allocation Failure:表示内存分配失败

离线分析报告:

        根据下图图表可以明显的看出是堆空间消耗完了,我们分配的是50m。但是具体是哪里分配了那么多空间,目前还不知道从哪里查看。

2、使用 jvisualvm 分析

        使用JDK自带的 jvisualvm 进行日志分析查看,可以通过找到安装目录(D:\Program Files\Java\jdk1.8.0_321\bin)或者通过 cmd 命令行唤出 GUI页面。

        打开工具页面后,选择左上角 “文件”菜单的 “装入” 按钮。将程序生成的堆 Dump 文件导入工具中,具体操作如下示意图:

        等待装载完成后,将会显示如下图所示的页面。能够查看到程序所运行的环境信息、版本信息以及发生了什么异常、异常所在的线程位置是哪里,都能查看得知:

        点击 “ 导致 OutOfMemoryError 异常错误的线程: http-nio-8080-exec-1”,可以看到具体是哪块的代码有这个问题,以及产生原因是什么。

        根据线程栈反馈的代码位置以及方法名,可以定位得知:

3、使用 MemoryAnalyzer 分析

        装载完成后显示如下页面,当然会有一个弹窗询问是否直接开始查看相关疑点缺陷。可以关掉进行手动查看:

2、案例二:元空间溢出

2.1、编写模拟代码

package blnp.net.cn.jvm.controller;import blnp.net.cn.jvm.entity.People;
import blnp.net.cn.jvm.service.PeopleSevice;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;/*** <p>内存问题演示代码</p>** @author lyb 2045165565@qq.com* @createDate 2024/4/10 19:33*/
@RestController
public class MemoryTestController {@Resourceprivate PeopleSevice peopleSevice;/*** 用途:案例1:模拟线上环境OOM* @author liaoyibin* @date 19:46 2024/4/10* @desc <pre>*     演示使用启动参数为:-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause -XX:MetaspaceSize=64m*     -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=system/heap/heapdump.hprof -Xms50m -Xmx50m -Xloggc:system/log/gc-oomHeap.log* </pre>**  执行该方法后,将会反馈异常如下:*  <pre>*      2024-04-10 20:08:12.057  INFO 44472 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms* addblnp.net.cn.jvm.service.PeopleSevice@64f50fcc* java.lang.OutOfMemoryError: Java heap space* Dumping heap to system/heap/heapdump.hprof ...* Unable to create system/heap/heapdump.hprof: File exists* 2024-04-10 20:08:12.581 ERROR 44472 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space] with root cause** java.lang.OutOfMemoryError: Java heap space*  </pre>* @params []* @param**/@RequestMapping("/add")public void addObject(){System.err.println("add"+peopleSevice);ArrayList<People> people = new ArrayList<>();while (true){people.add(new People());}}/*** 用途:案例2:模拟元空间OOM溢出* @author liaoyibin* @date 10:56 2024/4/11* @desc 1、项目启动参数配置:*  -XX:+PrintGCDetails -XX:MetaspaceSize=60m -XX:MaxMetaspaceSize=60m -Xss512K -XX:+HeapDumpOnOutOfMemoryError*  -XX:HeapDumpPath=system/heap/heapdumpMeta.hprof -XX:SurvivorRatio=8 -XX:+TraceClassLoading -XX:+TraceClassUnloading*  -XX:+PrintGCDateStamps -Xms60m -Xmx60M -Xloggc:system/log/gc-oomMeta.log**  2、执行异常:*  [Loaded java.nio.channels.CancelledKeyException from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]* Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: Metaspace* [Loaded java.lang.Throwable$WrappedPrintStream from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]** @params []* @param**/@RequestMapping("/metaSpaceOom")public void metaSpaceOom(){//用于 Java 虚拟机的类加载系统的管理接口。ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();while (true){Enhancer enhancer = new Enhancer();enhancer.setSuperclass(People.class);/*** setUseCache:选择为 true 的话,使用和更新一类具有相同属性生成的类的静态缓存,* 而不会在同一个类文件还继续被动态加载并视为不同的类,这个其实跟类的 equals() 和 hashCode() 有关,* 它们是与 cglib 内部的 class cache 的 key 相关的.** <p>*      测试结果的区别:*      1、false:由于元空间内存有限,而动态代理在不断的反射创建新的对象。最终导致元空间内存溢出了*      2、true:程序无影响,持续运行中(因为动态代理反射的类的结构属性都是一致的,所以可以直接共享使用)* </p>* **/enhancer.setUseCache(false);enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {System.out.println("我是加强类,输出print之前的加强方法");return methodProxy.invokeSuper(o,objects);});People people = (People)enhancer.create();people.print();System.out.println(people.getClass());//返回自 Java 虚拟机开始执行到目前已经加载的类的总数。System.out.println("totalClass:" + classLoadingMXBean.getTotalLoadedClassCount());//返回当前加载到 Java 虚拟机中的类的数量。System.out.println("activeClass:" + classLoadingMXBean.getLoadedClassCount());//返回自 Java 虚拟机开始执行到目前已经卸载的类的总数。System.out.println("unloadedClass:" + classLoadingMXBean.getUnloadedClassCount());}}
}

2.2、访问接口触发异常

java.lang.OutOfMemoryError: Metaspace
Dumping heap to system/heap/heapdumpMeta.hprof ...
Heap dump file created [29901158 bytes in 0.092 secs]
[Loaded sun.net.ResourceManager from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]
[Loaded java.io.InterruptedIOException from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]
[Loaded java.net.SocketException from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]
[Loaded java.nio.channels.CancelledKeyException from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]
Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: Metaspace
[Loaded java.lang.Throwable$WrappedPrintStream from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]
[Loaded sun.reflect.GeneratedSerializationConstructorAccessor27 from __JVM_DefineClass__]
[Loaded java.util.IdentityHashMap$KeySet from D:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar]

        可以明显看到程序已经抛出异常,反馈元空间内存不足了。此时我们也可以通过命令行(jstat -gc {pid}(程序的进程ID) 1000(单位毫秒,即每秒监测一次) 10(监测总次数)),可以查看得知以下结果:

        可以看到此时程序已经挂了,并且在断的进行 FullGC。但是回收后没有任何变化,空间并未能释放。

关键词解释:

  • S0C:新生代幸存者0区大小(单位:字节)
  • S1C:新时代幸存者1区大小
  • S0U:新生代幸存者0区,已使用大小
  • S1U:新时代幸存者1区,已使用大小
  • EC:伊甸园区大小
  • EU:伊甸园区已使用大小
  • OC:老年代区大小
  • OU:老年代区已使用大小
  • MC:方法区大小
  • MU:方法区已使用大小
  • CCSC:压缩类空间大小(在64位系统可能存在压缩为32位系统的场景)
  • CCSU:压缩类已使用大小
  • YGC:发生 YGC 的次数
  • YGCT:YGC 的时间
  • FGC:发生 FullGC的次数
  • FGCT:FullGC的时间
  • GCT:总时间

        除了通过命令行可以查看得知问题外,通过 jvisualvm 工具的可视化监控页面也能直观的查看到元空间溢出问题。因为我们启动参数设置的就是 60m,而程序在运行中在 60m 中没有任何降低,说明当前没有对象可以回收且由于没空间导致无法进行继续分配,进而抛出元空间溢出异常。

jvisualvm 分析Dump文件:

使用 MAT 分析日志:

        载入完成后,我们直接选择“直方图”进行查看。并对直方图列表中的项设置为按 packet 分组。

        随后对排名第一的包进行展开查看,发现占用最多的是 java.lang.reflect 中的 Method。对 Method 的记录进行右键引用跟踪查询。发现全是动态代理在不断的创建对象以及对应的属性和方法。

3、案例三:GC overhead limit exceeded

        详见代码内的说明描述:

package blnp.net.cn.jvm.demos;import java.util.ArrayList;
import java.util.List;
import java.util.UUID;/*** <p>测试 GC overhead limit exceeded</p>** @author lyb 2045165565@qq.com* @desc*  启动参数:-XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=system/heap/dumpExceeded.hprof -XX:+PrintGCDateStamps -Xms10m -Xmx10m -Xloggc:system/log/gc-oomExceeded.log* @createDate 2024/4/11 16:31*/
public class OomGcTest {public static void main(String[] args) {/** 执行结果:*      Connected to the target VM, address: '127.0.0.1:49836', transport: 'socket'* java.lang.OutOfMemoryError: GC overhead limit exceeded* Dumping heap to system/heap/dumpExceeded.hprof ...* Heap dump file created [10595605 bytes in 0.023 secs]* ************i: 63792* java.lang.OutOfMemoryError: GC overhead limit exceeded* 	at java.lang.String.substring(String.java:1933)* 	at java.util.UUID.digits(UUID.java:386)* **///test1();/** 执行结果:*    Connected to the target VM, address: '127.0.0.1:52213', transport: 'socket'* java.lang.OutOfMemoryError: Java heap space* Dumping heap to system/heap/dumpExceeded.hprof ...* Unable to create system/heap/dumpExceeded.hprof: File exists* ************i: 29114* 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:448)* 	at java.lang.StringBuilder.append(StringBuilder.java:136)* 	at java.lang.StringBuilder.append(StringBuilder.java:131)* 	at blnp.net.cn.jvm.demos.OomGcTest.test2(OomGcTest.java:84)* 	at blnp.net.cn.jvm.demos.OomGcTest.main(OomGcTest.java:31)* **/test2();}/*** 用途:第一段代码,运行期间将内容放入常量池* <pre>*     intern() 方法:*      1、如果字符串常量池里面已经包含了等于字符串 x 的字符串,那么就返回常量池中这个字符串的引用*      2、如果常量池中不存在,那么就会把当前字符串添加到常量池并返回这个字符串的引用* </pre>** @author liaoyibin* @date 16:43 2024/4/11* @params []* @param**/public static void test1() {int i = 0;List<String> list = new ArrayList<>();try {while (true) {list.add(UUID.randomUUID().toString().intern());i++;}} catch (Throwable e) {System.out.println("************i: " + i);e.printStackTrace();throw e;}}/*** 用途:第二段代码,不停的追加字符串 str* <pre>*      不停的追加字符串的特点是,前一个字符串对象引用将会作废(也就是下一次GC时可以回收)。*    该示例执行不会那么快抛出异常,是因为只有一个对象是在不断的变大且是无法回收的,直到内存溢出才会抛出异常,也就是为什么对比第一段*    代码为什么异常抛出的那么慢。*      两段代码执行后,抛出异常确不一样。这是因为在JDK6时新增的错误类型(GC overhead limit exceeded)限制,定义是:超过98%的时间用来*    做GC并且回收了不到 2% 的堆内存时就会抛出该异常。而我们的 test1() 方法就是这个原因。*      至于方法二为什么没有抛出这个异常,是因为我们是在不断的对字符串进行追加。而这个特点是字符串追加完后,之前的字符串对象是已经作废了并且是可以回收的状态。*    那么程序不断运行时,这个对象自然是越来越多。同理可回收的阈值肯定是不止 2% 的。而程序持续运行的期间,由于堆空间的有限而某个对象的不断变大。那肯定是会抛出*    堆空间不足的问题。总结来说就是:**    1、Java heap space:对应的 Demo 每次都能回收大部分的对象(也就是中间产生的UUID),只不过有一个对象是无法回收的,慢慢长大直到内存溢出。*    2、GC overhead limit exceeded:对应的 Demo 由于每个字符串都在被 list 引用,所以无法回收,很快就用完内存,触发不断回收的机制**    关于如何解决 GC overhead limit exceeded错误:*      1、排查程序中是否存在大量的死循环或有使用大内存的代码*      2、通过添加参数【-XX:-UseGCOverheadLimit】来禁用该检查,从而延迟程序的异常反馈。直到程序抛出:Java heap space 错误*      3、通过分析 dump 内存,确认是否有内存泄漏。如果没有则加大内存配置* </pre>** @author liaoyibin* @date 16:48 2024/4/11* @params []* @param**/public static void test2() {String str = "";Integer i = 1;try {while (true) {i++;str += UUID.randomUUID();}} catch (Throwable e) {System.out.println("************i: " + i);e.printStackTrace();throw e;}}
}

4、案例四:线程溢出

注意:切记,如果需要模拟该案例,一定要去虚拟机中去操作演示。否则在 mac/windows 系统中会直接关机重启;在Linux系统中会直接崩溃并且无法再进行任何命令操作!!!

4.1、Xss 参数使用 

        这里在复现该案例之前,我们先验证参数(-Xss512k)是否可以生效。新建一个java文件,如下所示:

/*** <p></p>** @author lyb 2045165565@qq.com* @createDate 2024/4/12 10:09*/
public class XssParamTest {public static void main(String[] args) {System.out.println("程序开始执行!");try {Thread.sleep(100000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("程序执行已完成!");}
}

        执行编译命令(javac XssParamTest.java)生成字节码文件,这里需要留意的是因为代码里存在中文。如果在Windows系统中执行时会抛出异常:

.\XssParamTest.java:10: 错误: 编码GBK的不可映射字符System.out.println("绋嬪簭寮?濮嬫墽琛岋紒");^
1 个错误

        因为字符集冲突,windows中文版,默认的字符集为:GBK,而当你的java文件当中的汉字不是字符集:GBK时,javac进行编译的时候就会报错。解决方式是在编译时指定编码参数(Linux中不需要)。

#编译
javac -encoding utf-8 .\XssParamTest.java#运行
java XssParamTest

        此时运行起该程序后,我们查看下该Java进程的栈空间大小。因为在JDK5以后默认的栈空间大小是 1M,因此这里确认是否是 1M。查看命令如下:

#查看进程ID
jps#查看栈空间大小
jinfo -flag ThreadStackSize {pid}

        看到这里可能会疑问,默认不应该是 1024吗,为什么结果是 0?-XX:ThreadStackSize=0不是说虚拟机栈大小为0,0表示为jvm默认值(这个虚拟机栈默认值是根据操作系统和JDK版本来的)。详见官网文档地址:

        而如果是在Linux系统中执行,对应的参数如下所示:

        验证修改栈空间大小,是否运行生效:

4.2、异常复现

        切记切记,一定要在虚机上操作复现。否则机器会挂掉!!

import java.util.concurrent.CountDownLatch;/*** <p>线程溢出异常复现</p>** @author lyb 2045165565@qq.com* @createDate 2024/4/12 11:04*/
public class NativeOutOfMemoryErrorTest {public static void main(String[] args) {for (int i = 0; ; i++) {System.out.println("i = " + i);new Thread(new HoldThread()).start();}}
}class HoldThread extends Thread {CountDownLatch cdl = new CountDownLatch(1);@Overridepublic void run() {try {cdl.await();} catch (InterruptedException e) {}}
}

        将程序上传至虚机或者虚机上新建该Java文件,并对文件进行编译输出。如下所示:

        这里开始执行程序,在执行过程也查看下当前程序进程的栈空间大小是多少。程序脚本的代码就是在不断的创建线程。

        此时虚机服务器已经挂掉了,无法输入任何命令。并且执行的程序已经抛出异常如下所示,需要特别留意的是目前创建的线程总数是(29989):

i = 29989
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native threadat java.lang.Thread.start0(Native Method)at java.lang.Thread.start(Thread.java:719)at NativeOutOfMemoryErrorTest.main(NativeOutOfMemoryErrorTest.java:14)

        这里我先将虚机关掉重启,再次执行并获取执行进程分配的栈空间大小具体是多少。由于我这边执行太快了,很快服务器就挂掉了无法执行其他命令进行检查,因此在代码打印新增休眠操作。延迟程序的执行。

        再次执行后创建的线程总数是(29968),可以看到和上一次相比差不了多少。这是因为我们给虚机分配的资源,目前最大只能创建这么多。因为默认分配的栈空间大小是 1M,此时如果我们再次执行的时候,指定栈空间大小。最终生成的线程数会更多还是更少?

4.3、问题分析

        通过 -Xss 可以设置每个线程栈大小的容量,JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。正常情况下,在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。能创建的线程数的具体计算公式如下:

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
  • MaxProcessMemory:指的是进程可寻址的最大空间,也就是一个进程的最大内存
  • JVMMemory:JVM内存
  • ReservedOsMemory:保留的操作系统内存
  • ThreadStackSize:线程栈的大小

        在java语言里,当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。

        由公式得出结论:你给JVM内存越多,那么你能创建的线程越少越容易发生java.lang.OutOfMemoryError: unable to create new native thread

        如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数。

  1. MaxProcessMemory 使用64位操作系统
  2. JVMMemory  减少JVMMemory的分配
  3. ThreadStackSize 减小单个线程的栈大小

        经实测,在32位windows系统下较为严格遵守;64位系统下只能保证正/负相关性,甚至说相关性也不能保证。即:在测试的过程中,64位操作系统下调整Xss的大小并没有对产生线程的总数产生影响,程序执行到极限的时候,操作系统会死机。无法看出效果

        在32位win7操作系统下测试,jdk版本1.8(适配32位操作系统)会发现调整Xss的大小会对线程数量有影响,如下表所示:

        由上可见,64位操作系统对于实验的结果是不明显的,但是32位操作系统对于Xss的设置对于实验结果是明显的,为什么会产生这样的结果?我们上面讲到过线程数量的计算公式:

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

        其中MaxProcessMemory表示最大寻址空间,在32位系统中,CPU的“寻址范围”就受到32个二进制位的限制,也就是说,假设它要访问内存,它的能力是,只能访问4G内存。

        32位二进制数最大值是11111111 11111111 11111111 11111111b,2的32次方  4294967296 = 4194304k(1k是1024) = 4096M(1M是1048576) = 4GB。也就是说32位CPU只能访问4GB的内存。再减去显卡上的显存等内存,可用内存要小于4G,所以32位操作系统可用线程数量是有限的。

        64位二进制数的最大值是11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111b,2的64次方 = 17179869184 GB,大家可以看看64位操作的寻址空间大小比32位操作系统多了太多,所以这也是为什么我们总是无法测试出很好效果的原因。

        但是事实上我们在64位系统中测试时,也还是发生了一样的异常,这是因为线程总数也受到系统空闲内存和操作系统的限制,检查是否该系统下有此限制:

#查看MaxProcessMemory,也就是系统最大pid值,在大型系统里可适当调大
cat /proc/sys/kernel/pid_max#查看系统当前的最大线程数阈值
cat /proc/sys/kernel/threads-max#查看当前用户最多可以运行多少进程或线程
ulimit -u#查看可以拥有虚拟内存的数量
cat /proc/sys/vm/max_map_count

max_map_count:文件包含限制一个进程可以拥有的VMA(虚拟内存区域)的数量。虚拟内存区域是一个连续的虚拟地址空间区域。

        在进程的生命周期中,每当程序尝试在内存中映射文件,链接到共享内存段,或者分配堆空间的时候,这些区域将被创建。

        调优这个值将限制进程可拥有VMA的数量。限制一个进程拥有VMA的总数可能导致应用程序出错,因为当进程达到了VMA上线但又只能释放少量的内存给其他的内核进程使用时,操作系统会抛出内存不足的错误。如果你的操作系统在NORMAL区域仅占用少量的内存,那么调低这个值可以帮助释放内存给内核用。

        真实测试发现,当我们增大了threads-max参数时(比如扩大10倍:echo 301290 > /proc/sys/kernel/threads-max),运行相关程序,发现可创建的线程数确实扩大了。但是仍受相关因素的影响,不能保证创建的线程数也扩大对应的倍数。要想创建更多线程,会发现在执行完程序报错的log日志(自动在当前目录下生成)中有说明:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/810217.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

环形队列的简单理解

多次遇到环形队列的情况&#xff0c;记不住什么情况是队列满&#xff0c;什么情况是队列空。一直也没有理解透彻。 仔细研究了一下&#xff0c;掌握了一些原理&#xff0c;记录一下。 1. 环形队列有一个头指针head&#xff0c;一个为指针tail。有一个疑问&#xff1a;head和ta…

更换淘宝镜像地址,旧的已经失效(https://registry.npm.taobao.org )

旧的镜像地址&#xff1a;npm install --registryhttps://registry.npm.taobao.org 新的镜像地址&#xff1a;npm install --registryhttps://registry.npmmirror.com

【2024最新博客美化教程重置版】今天教你如何使用SimpleMemory美化你的博客,体会一下大神是如何装逼的!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 SimpleMemory …

【算法基础】插入排序与二分查找、升级二分查找

文章目录 1. 插入排序1.1 插入排序的思想1.2 插入排序的实现 2. 普通二分查找2.1 普通二分查找的思想2.2 普通二分查找的实现 3. 升级二分查找3.1 升级二分查找思想3.2 升级二分查找实现 1. 插入排序 1.1 插入排序的思想 插入排序很类似于已有一副有序的扑克牌&#xff0c;不断…

【话题】AI技术创业有那些机会,简单探讨下

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景机会一、引言二、AI技术的创业机遇1.智能服务行业的兴起2.数据驱动的业务模式创新3.AI与产业融合的创新发展 三、AI技术创业的挑战1.技术门槛高2.法规政策的不确定性…

P1712 [NOI2016] 区间(线段树 + 贪心 + 双指针)

题目描述 在数轴上有 n 个闭区间从 1 至 n 编号&#xff0c;第 i 个闭区间为 [li​,ri​] 。 现在要从中选出 m 个区间&#xff0c;使得这 m 个区间共同包含至少一个位置。换句话说&#xff0c;就是使得存在一个 x &#xff0c;使得对于每一个被选中的区间 [li​,ri​]&#…

关于Ansible模块 ⑥

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 内容在继《关于Ansible的模块 ①》、《关于Ansible的模块 ②》、《关于Ansible的模块 ③》、《关于Ansible的模块 ④》与《关于a…

YOLOv8草莓生长状态(灰叶病缺钙需要肥料)检测系统(python开发,带有训练模型,可以重新训练,并有Pyqt5界面可视化)

本次检测系统&#xff0c;不仅可以检测图片、视频或摄像头当中出现的草莓叶子是否有灰叶病&#xff0c;还可以检测出草莓叶是否缺钙、是否需要施肥等状态。基于最新的YOLO-v8训练的草莓生长状态检测模型和完整的python代码以及草莓的训练数据&#xff0c;下载后即可运行&#x…

C语言——字符函数和字符串函数

Hello&#xff0c;大家好&#xff0c;今天和大家分享C语言中的几个字符函数和字符串函数&#xff0c;记得三连支持一下哦&#xff01; 在编程的过程中&#xff0c;我们经常要处理字符和字符串&#xff0c;为了⽅便操作字符和字符串&#xff0c;C语⾔标准库中提供了⼀系列库函数…

积分短信群发平台:精准营销新利器,助力企业高效触达目标用户

在当今数字化营销时代&#xff0c;精准营销已成为企业获取竞争优势的关键手段。积分短信群发平台作为一种高效、精准的营销工具&#xff0c;正逐渐受到越来越多企业的青睐。通过该平台&#xff0c;企业可以针对目标用户进行个性化的积分活动推广&#xff0c;实现精准营销&#…

leetcode328.奇偶链表

1. 题目描述 在线练习 2. 解题思路 这道题&#xff0c;官方给的是中等难度。其实是一道基础题&#xff0c;大家应该都可以写得出来。 题目中给的示例可以清楚的看到&#xff0c;合并前后的奇偶链的各自包含的节点的顺序是不变的&#xff0c;我们基本可以确定使用尾插法来合并…

IDEA2023连接服务器docker并部署ruoyi-cloud-plus项目

文章目录 TCP 方式连接docker1. 服务器docker配置修改查看虚拟机中Docker配置文件位置修改配置文件重启docker服务关闭防火墙 2. idea安装docker插件3. idea连接docker服务 部署ruoyi-cloud-plus项目1. 项目环境说明2. 安装Centos73. 安装docker4. idea配置服务器SSH连接5. ide…

三天做完pandas数据分析50题第一天

三天做完pandas数据分析50题第一天 第1题 将python的list转换为Series第2题 将字典转换为Series第3题 将Series转换成python的list第4题 使用numpy创建series。第5题 如何为Series添加新的元素&#xff1f;第6题 使用字典创建DataFrame第7题 给DataFrame设置索引列第8题 生成一…

个人博客项目笔记_07

写文章 写文章需要 三个接口&#xff1a; 获取所有文章类别 获取所有标签 发布文章 1. 所有文章分类 1.1 接口说明 接口url&#xff1a;/categorys 请求方式&#xff1a;GET 请求参数&#xff1a; 参数名称参数类型说明 返回数据&#xff1a; {"success":…

2024Mathorcup(妈妈杯)数学建模C题python代码+数据教学

2024Mathorcup数学建模挑战赛&#xff08;妈妈杯&#xff09;C题保姆级分析完整思路代码数据教学 C题题目&#xff1a;物流网络分拣中心货量预测及人员排班 因为一些不可抗力&#xff0c;下面仅展示部分代码&#xff08;很少部分部分&#xff09;和部分分析过程&#xff0c;其…

uni-app调用苹果登录,并获取用户信息

效果 模块配置 dev中的配置 需要开启登录的权限&#xff0c;然后重新下载配置文件&#xff0c;发布打包基座&#xff0c;再运行程序 代码 <button click"appleLogin">苹果登录</button>function appleLogin() {uni.login({provider: apple,success: …

备战蓝桥杯---刷杂题2

显然我们直接看前一半&#xff0c;然后我们按照斜行看&#xff0c;我们发现斜行是递增的&#xff0c;而同一行从左向右也是递增的&#xff0c;因此我们可以直接二分&#xff0c;同时我们发现对称轴的数为Ck,2k. 我们从16斜行枚举即可 #include<bits/stdc.h> using name…

git push报错remote: Please remove the file from history and try again

原因&#xff1a;上传文件超过100M&#xff0c;找到此文件删除即可。 1、查看是哪个文件过大&#xff0c;此处对用红框里面的 a6de1336c67c3bac77757c5eff8c8001823f7c92&#xff0c;得到具体的文件名称 git rev-list --objects --all | grep a6de1336c67c3bac77757c5eff8c80…

如果你想在Nomad Web中操作Excel数据

大家好&#xff0c;才是真的好。 没有意外&#xff0c;我猜你也会想在Nomad Web中操作Excel数据&#xff0c;毕竟你在Notes客户机中就是这样操作的。 不过&#xff0c;一个运行在浏览器中&#xff0c;一个运行在Notes客户机&#xff08;操作系统&#xff09;中。因此&#xf…

host文件nginx代理 综合理解

之前一直理解得很糙 导致遇到问题很迷糊 今天经过大佬两句话讲明白了 特此记录 host文件 首先host做了代理 也就是对浏览器的DNS寻址做了拦截 具体原理可以参照当我们在地址栏输入URL的时候浏览器发生了什么 例如127.0.0.1 www.baidu.com 将 127.0.0.1 www.baidu.com 链接自…