# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 12288 bytes for committing reserved memory.
# Possible reasons:
# The system is out of physical RAM or swap space
# The process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# JVM is running with Unscaled Compressed Oops mode in which the Java heap is
# placed in the first 4GB address space. The Java Heap base address is the
# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress
# to set the Java Heap base and to place the Java Heap above 4GB virtual address.
# This output file may be truncated or incomplete.
#
--------------- T H R E A D ---------------
Current thread (0x00007f1480287800): JavaThread "Keep-Alive-Timer" daemon [_thread_new, id=955887, stack(0x00007f12221cd000,0x00007f122220e000)]
Stack: [0x00007f12221cd000,0x00007f122220e000], sp=0x00007f122220cb40, free space=254k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xb5718d]
V [libjvm.so+0x50675a]
V [libjvm.so+0x93cfc0]
V [libjvm.so+0x9343be]
V [libjvm.so+0x93e557]
V [libjvm.so+0xafa7d6]
V [libjvm.so+0xafe97c]
V [libjvm.so+0x93a382]
C [libpthread.so.0+0x7ea5] start_thread+0xc5
--------------- P R O C E S S ---------------
Java Threads: ( => current thread )
=>0x00007f1480287800 JavaThread "Keep-Alive-Timer" daemon [_thread_new, id=955887, stack(0x00007f12221cd000,0x00007f122220e000)]
0x00007f1292a14000 JavaThread "SimpleAsyncTaskExecutor-122011" [_thread_blocked, id=955832, stack(0x00007f1222290000,0x00007f12222d1000)]
0x00007f1292a16000 JavaThread "SimpleAsyncTaskExecutor-122009" [_thread_blocked, id=955829, stack(0x00007f12222d1000,0x00007f1222312000)]
0x00007f1292a9a800 JavaThread "SimpleAsyncTaskExecutor-122007" [_thread_blocked, id=955823, stack(0x00007f122220e000,0x00007f122224f000)]
.....
Native memory allocation ,本地内存分配失败。
可能的解决办法:
线程数统计:32278 个SimpleAsyncTaskExecutor,开了好多线程啊! 应该是线程太多
SimpleAsyncTaskExecutor
是什么?这个org.springframework.core.task.SimpleAsyncTaskExecutor
类注释如下:
/**
* {@link TaskExecutor} implementation that fires up a new Thread for each task,
* executing it asynchronously.
*
* <p>Supports limiting concurrent threads through the "concurrencyLimit"
* bean property. By default, the number of concurrent threads is unlimited.
*
* <p><b>NOTE: This implementation does not reuse threads!</b> Consider a
* thread-pooling TaskExecutor implementation instead, in particular for
* executing a large number of short-lived tasks.
*
* @author Juergen Hoeller
* @since 2.0
* @see #setConcurrencyLimit
* @see SyncTaskExecutor
* @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
* @see org.springframework.scheduling.commonj.WorkManagerTaskExecutor
*/
@SuppressWarnings("serial")
SimpleAsyncTaskExecutor 不复用线程,每次都新启动一个线程.与问题表现一致,但是代码中没有显示使用这个类啊!谁在用呢???
SimpleAsyncTaskExecutor
谁在用?查看系统中所有多线程的部分,初步怀疑是@Async
注解使用了这个线程池,看源码验证。
* @see AnnotationAsyncExecutionInterceptor
* @see AsyncAnnotationAdvisor
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
String value() default "";
}
上边特意说明,查看AnnotationAsyncExecutionInterceptor
类(异步注解拦截器),AsyncAnnotationAdvisor
(异步注解通知和切入点定义类),显然要做默认线程池需要查看AnnotationAsyncExecutionInterceptor
类(异步注解拦截器)。
getDefaultExecutor方法如下:
@Override
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
目前可以确定,@Async
在不设置线程池的情况下,默认使用SimpleAsyncTaskExecutor
、
由于@Async标注的方法处理较慢,请求较多,造成创建大量的线程且没有执行完毕,线程回收不掉,占用本地内存过多,内存分配失败。
2. Spring Boot项目设置线程池,@Async注解复用线程,方法如下:
@Configuration
@EnableAsync
public class BeanConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(10);
// 设置队列容量
executor.setQueueCapacity(2000);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("hello-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。