聊一下JVM调优

闲聊一下:

这个JVM 相信大家都了解过 但是很少用这个东西 但是面试 一些高级架构师又是必问的一些问题 之前一直不了解这个东西 感觉就是面试造火箭 实际拧螺丝 用于筛选人才 毕业这么多年 也是很少接触这些 就大学的时候学过 简单了解过一些底层 ,找工作面试 倒是背过一些相关的甲骨文。

项目背景:

先简单说一下写这个的原因,我目前做的这个项目 有一个备份还原的功能 ,备份就是把整个数据库备份一下 还原就是执行一下这个sql 文件,其实这个功能很好理解,就备份数据库呗。代码过程没有用mysqldump 这个命令,而是自己写了一个存储过程 进行备份。至于为啥没用mysqldump 这个自带的备份还原功能,是因为操作系统的原因 麒麟系统这个命令属于半废状态 很卡 数据多的话 直接就用不了了 ,所以自己写了一个这个备份还原的存储过程,这里不过多叙述。

问题原因:由于加了某个功能 类似于多用户吧 导致数据剧增,之前一个用户用的挺好 没啥问题 现在整了多个用户 在还原 直接栈溢出了JVM 干满了 报错如下:

[xxxxx:xxxx:xxx] 2023-12-18 16:17:07.108 ERROR [http-nio-27000-exec-5] com.xxxx.services.cmp.dcs.config.ExceptionHandlerAdvice.handleException(198) Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055) [spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) [spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) [spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-embed-websocket-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at com.taiden.services.cmp.dcs.config.AccessFilter.doFilter(AccessFilter.java:67) [classes!/:?]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123) [druid-1.1.10.jar!/:1.1.10]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.springframework.security.web.FilterChainProxy V i r t u a l F i l t e r C h a i n . d o F i l t e r ( F i l t e r C h a i n P r o x y . j a v a : 320 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . a c c e s s . E x c e p t i o n T r a n s l a t i o n F i l t e r . d o F i l t e r ( E x c e p t i o n T r a n s l a t i o n F i l t e r . j a v a : 118 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . F i l t e r C h a i n P r o x y VirtualFilterChain.doFilter(FilterChainProxy.java:320) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.FilterChainProxy VirtualFilterChain.doFilter(FilterChainProxy.java:320)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.FilterChainProxyVirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.FilterChainProxy V i r t u a l F i l t e r C h a i n . d o F i l t e r ( F i l t e r C h a i n P r o x y . j a v a : 334 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . a u t h e n t i c a t i o n . A n o n y m o u s A u t h e n t i c a t i o n F i l t e r . d o F i l t e r ( A n o n y m o u s A u t h e n t i c a t i o n F i l t e r . j a v a : 111 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . F i l t e r C h a i n P r o x y VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.FilterChainProxy VirtualFilterChain.doFilter(FilterChainProxy.java:334)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.FilterChainProxyVirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.FilterChainProxy V i r t u a l F i l t e r C h a i n . d o F i l t e r ( F i l t e r C h a i n P r o x y . j a v a : 334 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . s a v e d r e q u e s t . R e q u e s t C a c h e A w a r e F i l t e r . d o F i l t e r ( R e q u e s t C a c h e A w a r e F i l t e r . j a v a : 63 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . F i l t e r C h a i n P r o x y VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.FilterChainProxy VirtualFilterChain.doFilter(FilterChainProxy.java:334)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.FilterChainProxyVirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy V i r t u a l F i l t e r C h a i n . d o F i l t e r ( F i l t e r C h a i n P r o x y . j a v a : 334 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . h e a d e r . H e a d e r W r i t e r F i l t e r . d o H e a d e r s A f t e r ( H e a d e r W r i t e r F i l t e r . j a v a : 92 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . h e a d e r . H e a d e r W r i t e r F i l t e r . d o F i l t e r I n t e r n a l ( H e a d e r W r i t e r F i l t e r . j a v a : 77 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . w e b . f i l t e r . O n c e P e r R e q u e s t F i l t e r . d o F i l t e r ( O n c e P e r R e q u e s t F i l t e r . j a v a : 119 ) [ s p r i n g − w e b − 5.2.4. R E L E A S E . j a r ! / : 5.2.4. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . F i l t e r C h a i n P r o x y VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE] at org.springframework.security.web.FilterChainProxy VirtualFilterChain.doFilter(FilterChainProxy.java:334)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)[springweb5.2.4.RELEASE.jar!/:5.2.4.RELEASE]atorg.springframework.security.web.FilterChainProxyVirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.FilterChainProxy V i r t u a l F i l t e r C h a i n . d o F i l t e r ( F i l t e r C h a i n P r o x y . j a v a : 334 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . c o n t e x t . r e q u e s t . a s y n c . W e b A s y n c M a n a g e r I n t e g r a t i o n F i l t e r . d o F i l t e r I n t e r n a l ( W e b A s y n c M a n a g e r I n t e g r a t i o n F i l t e r . j a v a : 56 ) [ s p r i n g − s e c u r i t y − w e b − 5.2.2. R E L E A S E . j a r ! / : 5.2.2. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . w e b . f i l t e r . O n c e P e r R e q u e s t F i l t e r . d o F i l t e r ( O n c e P e r R e q u e s t F i l t e r . j a v a : 119 ) [ s p r i n g − w e b − 5.2.4. R E L E A S E . j a r ! / : 5.2.4. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . s e c u r i t y . w e b . F i l t e r C h a i n P r o x y VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE] at org.springframework.security.web.FilterChainProxy VirtualFilterChain.doFilter(FilterChainProxy.java:334)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)[springsecurityweb5.2.2.RELEASE.jar!/:5.2.2.RELEASE]atorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)[springweb5.2.4.RELEASE.jar!/:5.2.4.RELEASE]atorg.springframework.security.web.FilterChainProxyVirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:109) [spring-boot-actuator-2.2.5.RELEASE.jar!/:2.2.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.coyote.AbstractProtocol C o n n e c t i o n H a n d l e r . p r o c e s s ( A b s t r a c t P r o t o c o l . j a v a : 868 ) [ t o m c a t − e m b e d − c o r e − 9.0.31. j a r ! / : 9.0.31 ] a t o r g . a p a c h e . t o m c a t . u t i l . n e t . N i o E n d p o i n t ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.31.jar!/:9.0.31] at org.apache.tomcat.util.net.NioEndpoint ConnectionHandler.process(AbstractProtocol.java:868)[tomcatembedcore9.0.31.jar!/:9.0.31]atorg.apache.tomcat.util.net.NioEndpointSocketProcessor.doRun(NioEndpoint.java:1639) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_231]
at java.util.concurrent.ThreadPoolExecutor W o r k e r . r u n ( T h r e a d P o o l E x e c u t o r . j a v a : 624 ) [ ? : 1.8. 0 2 31 ] a t o r g . a p a c h e . t o m c a t . u t i l . t h r e a d s . T a s k T h r e a d Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_231] at org.apache.tomcat.util.threads.TaskThread Worker.run(ThreadPoolExecutor.java:624)[?:1.8.0231]atorg.apache.tomcat.util.threads.TaskThreadWrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.31.jar!/:9.0.31]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_231]
Caused by: java.lang.OutOfMemoryError: Java heap space

排查问题:

看到这个报错,我们就大致猜出来就是数据量太大 导致JVM栈溢出了没看出来的 自行百度或者csdn 瞅瞅。

java.lang.OutOfMemoryError: Java heap space (JVM 堆空间溢出)简单来说就是在创建新的对象时, 堆内存中的空间不足以存放新创建的对象,导致此种问题的发生。

现在终于可以聊聊JVM了 我就简单总结一下
1.先说一下啥是JVM吧

JVM是Java虚拟机,是Java Virtual Machine的缩写。Java借助JVM实现了平台无关性,只需要在操作系统平台上部署JVM,Java编译生成的目标代码(字节码)就可以在Java虚拟机上运行,使得Java语言在不同平台上运行时,不需要重新编译,从而实现了一次编译多处运行。 这个也是当年java 能火的根本原因 当年的黑科技术(跨平台技术的实现)

整体架构如下
聊一下JVM调优_第1张图片

2.JVM内部构造如下
聊一下JVM调优_第2张图片

堆(heap):这块区域主要存放对象的,比如说我们程序中new User()对象它就会被分配到这块区域,这块区域是共享的,也就是所有线程都可以访问该区域的对象,堆也是垃圾回收主要区域。

java虚拟机栈 (vm stack): 这块区域存放我们线程运行时的一些数据,它是每个线程私有的,可以理解为一个线程就对应的着一个java虚拟机栈,它里面就是一个个的栈帧组成的,一个方法就是一个栈帧,栈帧里面有局部变量表,操作数栈,常量池的引用,方法返回地址等;

比如下面这段代码:

public static void main(String[] args) {
int a=1;
int b=2;
int c= a+b;
System.out.println©;
c=0;
}
这段代码就是计算a+b 为c,然后调用println方法打印c的值。

这里面 a,b,c 就在局部变量表中,在算c的时候就是使用的操作数栈算的,然后调用println方法打印c其实就是往java 虚拟机栈 压入一个println 方法的栈帧。

本地方法栈(native stack):它与java虚拟机栈功能差不多,只不过java虚拟机栈是运行的java方法,而本地方法栈主要是执行的native方法。在hotspot虚拟机中将本地方法栈与java虚拟机栈合二为一。

元数据(Metaspace):这个是java8 的新概念,以前叫方法区,主要是存放着我们的class类信息,我们常说的类加载器其实就是将class文件加载到这个区域,这个区域还保存着我们定义的常量,也就是常量池。

程序计数器(Program Counter Register):它也叫做pc寄存器,每个线程一个程序计数器,它保存着当前线程执行的指令地址,当执行的是java 方法的时候,程序计数器保存的是当前需要执行的指令地址,当执行的是native 方法的时候,程序计数器保存的就是undefined。
聊一下JVM调优_第3张图片

3.回归主题 现在在看上面那个报错 是不是很熟悉 没错 就是堆内存满了
java.lang.OutOfMemoryError: Java heap space

分析原因:之前操作其他的过程导致GC 没有工作 没有实现垃圾回收
聊一下JVM调优_第4张图片

分析一下:正在使用的工作的肯定是不能释放的,而不再使用的部分是肯定要释放的,那中间那一堆它一部分正在使用,而一部分又不再使用,要不要释放呢?整体来说是不释放的 等到这个对象彻底完全不使用,才真正释放

以上总结起来就一句话:垃圾回收的基本单位是“对象”,而不是“字节”

4.垃圾回收的过程:

一般分为两个阶段

找垃圾 并且判断是不是垃圾

释放垃圾

5.找垃圾/判定垃圾

如何找垃圾/判定垃圾呢?当下主流的思路,有两种方案:

基于引用计数(不是Java中采取的方案,这是别的语言,像Python采取的方案)

针对每个对象,都会额外引入一小块内存,保存这个对象有多少个引用指向它

当这个内存不再使用的时候就释放了,而当引用计数为0的时候,就不再使用了

引用计数的优缺点:

空间利用率比较低!!每个 new 的对象都得搭配个计数器(计数器假设 4个字节),如果对象本身很大(几百个字节),多出来4个字节,就不算什么,但是如果本身对象很小(自己才4个字节),多出4个字节,相当于空间被浪费了一半

会有循环引用的问题

基于可达性分析(这个是Java采取的方案)

Java使用的就是此种算法,通过一系列的称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的。此算法解决了上述循环引用的问题。

可作为 GC Roots 的对象

在Java语言中,可作为 GC Roots 的对象举例几种:   a. 虚拟机栈(栈帧中的本地变量表)中引用的对象。   b. 方法区中类静态属性引用的对象。   c. 方法区中常量引用的对象。   d. 本地方法栈中 JNI(Native方法)引用的对象

总结一句话就是,除了堆空间外的一些结构,比如 虚拟机栈、本地方法栈、方法区、字符串常量池 等地方对堆空间进行引用的,都可以作为GC Roots进行可达性分析。

其中虚拟机栈和本地方法栈都是线程私有的内存区域,只要线程没有终止,就能确保它们中引用的对象的存活。而方法区中类静态属性引用的对象是显然存活的。常量引用的对象在当前可能存活,因此也可能是 GC roots 的一部分。

二次标记回收对象

不可达的对象将暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:

1、如果对象在进行可达性分析后发现没有与 GC Roots 相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize() 方法。

2、当对象没有重写 finalize() 方法,或者 finalize() 方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”,直接进行第二次标记。

3、如果这个对象被判定为有必要执行 finalize() 方法,那么这个对象将会放置在一个叫做 F-Queue 的队列之中,并在稍后由一个由虚拟机自动建立的、低优先级的 Finalizer 线程去执行它。

这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,因为如果一个对象在 finalize() 方法中执行缓慢,将很可能会一直阻塞 F-Queue 队列,甚至导致整个内存回收系统崩溃。

对象的finalization机制

ava语言提供了对象终止(finalization)机制来允许开发人员提供对象被销毁之前的自定义处理逻辑。

当垃圾回收器发现没有引用指向一个对象,即:垃圾回收此对象之前,总会先调用这个对象的finalize()方法。

finalize() 方法允许在子类中被重写,用于在对象被回收时进行资源释放。通常在这个方法中进行一些资源释放和清理的工作,比如关闭文件、套接字和数据库连接等。

注意:永远不要主动调用某个对象的finalize()方法应该交给垃圾回收机制调用。 理由包括下面三点:

1、在finalize()时可能会导致对象复活。   2、finalize()方法的执行时间是没有保障的,它完全由Gc线程决定,极端情况下,若不发生GC,则finalize()方法将没有执行机会。因为优先级比较低,即使主动调用该方法,也不会因此就直接进行回收   3、一个糟糕的finalize()会严重影响Gc的性能

6.Java 堆永久代的回收

永久代(方法区)的垃圾收集主要回收两部分内容:废弃常量和无用的类。

1、回收废弃常量与回收 Java 堆中的对象非常类似。以常量池中字面量的回收为例,假如一个字符串"abc"已经进入了常量池中,但是当前系统没有任何一个 String 对象是叫做"abc"的,也没有其他地方引用了这个字面量,如果这时发生内存回收,而且必要的话,这个"abc"常量就会被系统清理出常量池。常量池中的其他类(接口)、方法、字段的符号引用也与此类似。

2、类需要同时满足下面 3 个条件才能算是“无用的类”:    a. 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。    b. 加载该类的 ClassLoader 已经被回收。    c. 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。   虚拟机可以对满足上述 3 个条件的无用类进行回收,这里说的仅仅是“可以”,而并不是和对象一样,不使用了就必然会回收。

在大量使用反射、动态代理、CGLib 等 ByteCode 框架、动态生成 JSP 以及 OSGi 这类频繁自定义 ClassLoader 的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。

7.垃圾收集算法

7.1 标记-清除算法

最基础的收集算法是“标记-清除”(Mark-Sweep)算法,分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

它的主要不足有两个:   1、效率问题,标记和清除两个过程的效率都不高;   2、空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

总结:内存碎片就是:比如空闲的内存有很多,假设一共是 1G,如果要申请 500M 内存,也是可能申请失败的,因为要申请 500M 的内存 必须是连续的,每次申请,都是申请的连续的内存空间,而这里的 1G 可能是多个 碎片加在一起 才 1G,可用的并不多

7.2 复制算法

为了解决效率问题,一种称为“复制”(Copying)的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为了原来的一半。

新生代中98%的对象都是 ‘‘朝生夕死’’ 的,所以并不需要按照1:1的比例来划分空间,而是将内存(新生代内存)分为一块比较大的Eden(伊甸园)和两块较小的Survivor(幸存者)空间,每次使用Eden和其中一块Survivor(两个Survivor区域一个称为From区,另一个称为To区)。当回收时,将Eden和Survivor中还存活的对象一次性复制到另一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间

HotSpot默认Eden:Survivor From:Survivor To=8:1:1,所以每次新生代可用内存空间为整个新生代容量的90%,而剩下的10%用来存放回收后存活的对象。

当Survivor空间不够用时,需要依赖其它内存(老年代进行分配担保)

HotSpot实现复制算法的流程:

1、 当Eden区满的时候,会触发第一次Minor gc,把还活着的对象拷贝到Survivor From区;当Eden区再次触发Minor gc的时候,会扫描Eden和From区域,对两个区域进行垃圾回收,经过这次回收后还存活的对象,直接赋值到To区域,并将Eden和From区域清空。   2、当后续Eden又发生Minor gc的时候,会对Eden和To区域进行垃圾回收,存活的对象复制到From区域,并将Eden和To区域清空。   3、 部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终还是存活,就存入老年代。

优缺点:此时内存碎片问题就迎刃而解了!

但是复制算法也有问题:

内存空间利用率低(只能用一般的空间)

如果要保留的的对象多,要释放的对象少,此时复制开销就很大

7.3 标记-整理算法

复制算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。更关键的是,如果不想浪费 50% 的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都 100% 存活的极端情况,所以在老年代一般不能直接选用这种算法。

根据老年代的特点,有人提出了另外一种“标记-整理”(Mark-Compact)算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,

优缺点:这个方案空间利用率是高了,但是仍然没有解决复制/搬运元素开销大的问题

7.4分代收集算法

当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,根据对象存活周期的不同将内存划分为几块并采用不用的垃圾收集算法。

一般是把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。

分代回收中,还有一个特殊情况:有一类对象可以直接进入老年代(大对象,占有内存多的对象),大对象拷贝开销比较大,不适合使用复制算法!

8.垃圾回收器

上面说的找垃圾,和释放垃圾,说的都是算法思想,不是具体落地实现,在JVM里,真正实现上述算法的模块称为“垃圾回收器”。

Serial 收集器

特点:Serial 即串行的意思,也就是说它以串行的方式执行,单线程、简单高效(限定单个CPU的环境来说),Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程手机效率。收集器进行垃圾回收时,必须暂停其他所有的工作线程,直到它结束(Stop The World)。

ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本。除了使用多线程外其余行为均和Serial收集器一模一样(参数控制、收集算法、Stop The World、对象分配规则、回收策略等)。

特点: 多线程、ParNew收集器默认开启的收集线程数与CPU的数量相同,在CPU非常多的环境中,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。和Serial收集器一样存在Stop The World问题

应用场景: ParNew收集器是许多运行在Server模式下的虚拟机中首选的新生代收集器,因为它是除了Serial收集器外,唯一一个能与CMS收集器配合工作的。

Parallel Scavenge 收集器

与吞吐量关系密切,故也称为吞吐量优先收集器。

特点: 属于新生代收集器也是采用复制算法的收集器,又是并行的多线程收集器(与ParNew收集器类似)。该收集器的目标是达到一个可控制的吞吐量。还有一个值得关注的点是:GC自适应调节策略(与ParNew收集器最重要的一个区别)

GC自适应调节策略:Parallel Scavenge收集器可设置-XX:+UseAdptiveSizePolicy参数。当开关打开时不需要手动指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等,虚拟机会根据系统的运行状况收集性能监控信息,动态设置这些参数以提供最优的停顿时间和最高的吞吐量,这种调节方式称为GC的自适应调节策略。 Parallel Scavenge收集器使用两个参数控制吞吐量:

XX:MaxGCPauseMillis 控制最大的垃圾收集停顿时间 XX:GCRatio 直接设置吞吐量的大小

Serial Old 收集器

Serial Old是Serial收集器的老年代版本。

特点:同样是单线程收集器,采用标记-整理算法 Serial / Serial Old收集器工作过程图(Serial收集器图示相同)

Parallel Old 收集器

Parallel Old是Parallel Scavenge收集器的老年代版本。

特点:多线程,采用标记-整理算法。

应用场景:注重高吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge+Parallel Old 收集器。

Parallel Scavenge/Parallel Old收集器工作过程图

CMS收集器

一种以获取最短回收停顿时间为目标的收集器。

特点:基于标记-清除算法实现。并发收集、低停顿。

应用场景:适用于注重服务的响应速度,希望系统停顿时间最短,给用户带来更好的体验等场景下。如web程序、b/s服务。

CMS收集器的GC周期主要由7个阶段组成,其中有两个阶段会发生stop-the-world,其他阶段都是并发执行的。(亦有4个阶段、6个阶段等说法)

1: Initial Mark(初始化标记) 初始化标记阶段,是CMS GC的第一个阶段,也是标记阶段的开始。主要工作是标记GC Roota可直达的存活对象。 主要标记过程:

从GC Roots遍历可直达的老年代对象 遍历被新生代存活对象所引用的老年代对象 程序执行情况:

支持单线程或并行标记 发生stop-the-world,暂停所有应用线程 2: Concurrent Mark(并发标记) 在该阶段,GC线程和应用线程将并发执行。也就是说,在第一个阶段(Initial Mark)被暂停的应用线程将恢复运行。

并发标记阶段的主要工作是,通过遍历第一个阶段(Initial Mark)标记出来的存活对象,继续递归遍历老年代,并标记可直接或间接到达的所有老年代存活对象。

由于在并发标记阶段,应用线程和GC线程是并发执行的,因此可能产生新的对象或对象关系发生变化,例如:

新生代的对象晋升到老年代 直接在老年代分配对象 老年代对象的引用关系发生变更 等等 对于这些对象,后面需要重新标记以防止被遗漏(漏标)。为了提高重新标记的效率,本阶段会把这些发生变化的对象所在的Card标识为Dirty,这样后续就只需要扫描这些Dirty Card的对象,从而避免扫描整个老年代。

3: Concurrent Preclean(并发预清理) 该阶段将会重新扫描前一个阶段标记的Dirty对象,并标记被Dirty对象直接或间接引用的对象,然后清除Card标识。

标记被Dirty对象直接或间接引用的对象 清除Dirty对象的Card标识 4: Concurrent Abortable Preclean(可中止的并发预清理) 本阶段尽可能承担更多的并发预处理工作,从而减轻在Final Remark阶段的stop-the-world。

在该阶段,主要循环的做两件事:

处理 From 和 To 区的对象,标记可达的老年代对象 和上一个阶段一样,扫描处理Dirty Card中的对象 具体执行多久,取决于许多因素,满足其中一个条件将会中止运行:

执行循环次数达到了阈值 执行时间达到了阈值 新生代Eden区的内存使用率达到了阈值 5: Final Remark(重新标记) 预清理阶段也是并发执行的,并不一定是所有存活对象都会被标记,因为在并发标记的过程中对象及其引用关系还在不断变化中。 因此,需要有一个stop-the-world的阶段来完成最后的标记工作,这就是重新标记阶段(CMS标记阶段的最后一个阶段)。主要目的是重新扫描之前并发处理阶段的所有残留更新对象。

主要工作:

遍历新生代对象,重新标记;(新生代会被分块,多线程扫描) 根据GC Roots,重新标记 遍历老年代的Dirty Card,重新标记。这里的Dirty Card,大部分已经在Preclean阶段被处理过了

G1收集器

G1起源 G1从jdk7开始,jdk9被设为默认垃圾收集器;目标就是彻底替换掉CMS

CMS垃圾回收器缺点 并发清理阶段存在浮动垃圾; – 并发执行导致 fgc算法是标记清除,会产生磁盘碎片 – 标记整理算法导致 新生代配合ParNewGC使用,存在STW问题。 — 时间不可控,如果heap很大,可能GC时间很大,影响线上服务 G1内存分配策略 将内存分成一个个的Region,且不要求各部分是连续的。G1在逻辑上还是划分Eden、Survivor、OLd,但是物理上他们不是连续的。 每个Region的大小在JVM启动时就确定,JVM通常生成2048个左右的heap区, 根据堆内存的总大小,区的size范围为1-32Mb,一般4M.

region类型:

三种常见: Eden、Survivor、old generation(老年代)区 巨无霸区:保存比标准region区大50%及以上的对象,存储在一组连续的区中.转移会影响GC效率,标记阶段发现巨型对象不再存活时,会被直接回收 未使用区:未被使用的region 特别说明:某个region的类型不是固定的,比如一次ygc过后,原来的Eden的分区就会变成空闲的可用分区,随后也可能被用作分配巨型对象

G1垃圾回收算法

收集整体是使用“标记-整理”

Region之间基于“复制”算法。

G1的运行过程与CMS大体相似,分为以下四个步骤:

初始标记(Initial Marking):仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿。

并发标记( Concurrent Marking):从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,并发时有引用变动的对象会产生漏标问题,G1中会使用SATB来解决,后面会介绍。

最终标记(Final Marking):对用户线程做一个短暂的暂停,用于处理并发标记阶段仍遗留下来的最后那少量的SATB记录(漏标对象)。

筛选回收(Live Data Counting and Evacuation):负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多个收集器线程并行完成的 TAMS指针:在并发标记过程中,如何进行新对象的内存分配呢? G1有两个TAMS指针,把Region中的一部分空间划分出来用于并发回收过程中的新对象的分配。并发回收时新分配的对象地址都必须在这两个指针之上,G1收集器默认在这个地址上的对象是存活的,不纳入回收范围。

G1中重要数据结构 待回收集,CSet(Collection Set ) 收集集合(CSet)代表每次GC暂停时回收的一系列目标分区。在任意一次收集暂停中,CSet所有分区都会被释放,内部存活的对象都会被转移到分配的空闲分区中。因此无论是年轻代收集,还是混合收集,工作的机制都是一致的。年轻代收集CSet只容纳年轻代分区,而混合收集会通过启发式算法,在老年代候选回收分区中,筛选出回收收益最高的分区添加到CSet中。

9.以上简单了解一下 现在回归主题 这个问题怎么解决
提升Java heap size

增加堆内存空间设置,此种方式容易操作。可以较快解决当前问题,但是总体来说还是需要找到项目代码中的问题才是最优解,毕竟内存总是有限的

客户生产环境的服务器是8g内存,并且操作系统是比较老的windows server 2008服务器。在部署项目时使用winsw工具将jar包安装为服务。因此在项目启动时,增加内存参数,修改后配置如下:

app-id app-name service application descriptions java -jar -server -Xms4096m -Xmx4096m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m "D:\application\api-rest-1.0.0.jar" ​ Automatic %BASE%\logs rotate ​

JVM参数配置参考

服务器内存8G ,所以可以采取以下配置:
set JAVA_OPTS=-server -Xms4096m -Xmx4096m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m
服务器内存4G ,所以可以采取以下配置:
set JAVA_OPTS=-server -Xms2048m -Xmx2048m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m
服务器内存2G ,所以可以采取以下配置:
set JAVA_OPTS=-server -Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m
服务器内存1G ,所以可以采取以下配置:
set JAVA_OPTS=-server -Xms512m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=256M -XX:MaxPermSize=256m
服务器内存512M ,所以可以采取以下配置:
set JAVA_OPTS=-server -Xms256m -Xmx256m -XX:PermSize=256M -XX:MaxNewSize=128m -XX:MaxPermSize=128m
堆区参数配置说明

堆区:通过new的方式创建的对象(一个类的实例)、数组所占的空间。所有的线程共享该区域 堆区还细分为新生代(Eden空间、From Survivor空间、To Survivor空间)、老年代(Tenured Generation空间)

参数名 含义
-Xms java虚拟机初始化时的最小内存
-Xmx java虚拟机可使用的最大内存

通常会将-Xms 与-Xmx两个参数的配置相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源

参数名 含义
-XX:newSize 表示对象创建初始内存的大小,应小于-Xms的值
-XX:MaxnewSize 表示对象创建可被分配的内存的最大上限,应小于-Xmx的值
-Xmn jdk1.4后对-XX:newSize、-XX:MaxnewSize两个参数同时进行配置

非堆区参数配置说明

非堆区:代码、常量、外部访问(比如流在传输数据时所占用的资源)等,java垃圾回收机制只作用于堆区,非堆区不会被java垃圾回收机制进行处理

参数名 含义
-XX:PermSize 表示非堆区初始内存分配大小(方法区)
-XX:MaxPermSize 表示对非堆区分配的内存的最大上限(方法区)

在配置之前一定要慎重的考虑一下自身软件所需要的非堆区内存大小,因为此处内存是不会被java垃圾回收机制进行处理的地方。并且更加要注意的是最大堆内存与最大非堆内存的和绝对不能够超出操作系统的可用内存。

你可能感兴趣的:(jvm)