Skip to content

ReloadableResourceBundleMessageSource locks properties hashmap and fails under load. [SPR-10500] #15133

@spring-projects-issues

Description

@spring-projects-issues

Ronald R. DiFrango opened SPR-10500 and commented

The ReloadableResourceBundleMessageSource class locks the whole hashmap that holds properties and in our case is making the network call (after acquiring lock). This terribly slows down the property look-up. Under load it’s more significant as multiple threads could potentially try to load the files if there is a timeout.

Ideally we’d like a background thread load the properties after a timeout and put them into hashmap without locking as we are read-heavy and can tolerate stale entries.

Another option is to use a concurrent hashmap. Therefore the change for RRB should allow a backing map and whether to lock or not.

Here is the stack trace, notice the line in red is holding lock on a hashmap, which is the hashmap that holds properties:

"[ACTIVE] ExecuteThread: '150' for queue: 'weblogic.kernel.Default (self-tuning)'" id=8927 idx=0x2fc tid=30297 prio=5 alive, native_blocked, daemon
                at jrockit/net/SocketNativeIO.readBytesPinned(Ljava/io/FileDescriptor;[BIII)I(Native Method)
                at jrockit/net/SocketNativeIO.socketRead(SocketNativeIO.java:32)[inlined]
                at java/net/SocketInputStream.socketRead0(Ljava/io/FileDescriptor;[BIII)I(SocketInputStream.java)[inlined]
                at java/net/SocketInputStream.read(SocketInputStream.java:129)[optimized]
                at java/io/BufferedInputStream.fill(BufferedInputStream.java:218)
                at java/io/BufferedInputStream.read1(BufferedInputStream.java:258)[optimized]
                at java/io/BufferedInputStream.read(BufferedInputStream.java:317)[optimized]
                ^-- Holding lock: java/io/BufferedInputStream@0x10f0f4cc0[thin lock]
                at weblogic/net/http/MessageHeader.isHTTP(MessageHeader.java:224)
                at weblogic/net/http/MessageHeader.parseHeader(MessageHeader.java:148)[optimized]
                at weblogic/net/http/HttpClient.parseHTTP(HttpClient.java:468)[optimized]
                at weblogic/net/http/HttpURLConnection.getInputStream(HttpURLConnection.java:395)[inlined]
                at weblogic/net/http/SOAPHttpURLConnection.getInputStream(SOAPHttpURLConnection.java:37)[optimized]
                ^-- Holding lock: weblogic/net/http/SOAPHttpURLConnection@0x10f0f2550[biased lock]
                at weblogic/net/http/HttpURLConnection.getResponseCode(HttpURLConnection.java:983)[optimized]
                at org/springframework/core/io/AbstractFileResolvingResource.exists(AbstractFileResolvingResource.java:103)[optimized]
                at com/capitalone/epf/context/support/ReloadableResourceBundleMessageSource.refreshProperties(ReloadableResourceBundleMessageSource.java:131)[optimized]
                at org/springframework/context/support/ReloadableResourceBundleMessageSource.getProperties(ReloadableResourceBundleMessageSource.java:439)[inlined]
                at org/springframework/context/support/ReloadableResourceBundleMessageSource.resolveCodeWithoutArguments(ReloadableResourceBundleMessageSource.java:272)[optimized]
                ^-- Holding lock: java/util/HashMap@0x10d49e228[fat lock]
                at org/springframework/context/support/AbstractMessageSource.getMessageInternal(AbstractMessageSource.java:193)[inlined]
                at org/springframework/context/support/AbstractMessageSource.getMessage(AbstractMessageSource.java:127)[optimized]
                at org/springframework/context/support/AbstractApplicationContext.getMessage(AbstractApplicationContext.java:1210)[optimized]
                at org/springframework/web/servlet/tags/MessageTag.resolveMessage(MessageTag.java:227)[inlined]
                at org/springframework/web/servlet/tags/MessageTag.doStartTagInternal(MessageTag.java:165)[optimized]
                at org/springframework/web/servlet/tags/RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79)[optimized]
                at jsp_servlet/_web_45_inf/_views/__viewrequiredinformation._jsp__tag12(__viewrequiredinformation.java:1381)
                at jsp_servlet/_web_45_inf/_views/__viewrequiredinformation._jspService(__viewrequiredinformation.java:441)
                at weblogic/servlet/jsp/JspBase.service(JspBase.java:34)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)[inlined]
                at weblogic/servlet/internal/ServletStubImpl.execute(ServletStubImpl.java:300)[optimized]
                at weblogic/servlet/internal/ServletStubImpl.execute(ServletStubImpl.java:183)[inlined]
                at weblogic/servlet/internal/RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:523)[optimized]
                at weblogic/servlet/internal/RequestDispatcherImpl.forward(RequestDispatcherImpl.java:253)[optimized]
                at org/springframework/web/servlet/view/InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)[optimized]
                at org/springframework/web/servlet/view/AbstractView.render(AbstractView.java:262)[optimized]
                at org/springframework/web/servlet/DispatcherServlet.render(DispatcherServlet.java:1157)[optimized]
                at org/springframework/web/servlet/DispatcherServlet.doDispatch(DispatcherServlet.java:927)[optimized]
                at org/springframework/web/servlet/DispatcherServlet.doService(DispatcherServlet.java:827)[inlined]
                at org/springframework/web/servlet/FrameworkServlet.processRequest(FrameworkServlet.java:882)[inlined]
                at org/springframework/web/servlet/FrameworkServlet.doGet(FrameworkServlet.java:778)[optimized]
                at javax/servlet/http/HttpServlet.service(HttpServlet.java:707)[optimized]
                at javax/servlet/http/HttpServlet.service(HttpServlet.java:820)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)[inlined]
                at weblogic/servlet/internal/ServletStubImpl.execute(ServletStubImpl.java:300)[optimized]
                at weblogic/servlet/internal/TailFilter.doFilter(TailFilter.java:26)[optimized]
                at weblogic/servlet/internal/FilterChainImpl.doFilter(FilterChainImpl.java:56)[optimized]
                at com/capitalone/epf/context/filters/EPFContextServletFilter.doFilter(EPFContextServletFilter.java:89)[optimized]
                at weblogic/servlet/internal/FilterChainImpl.doFilter(FilterChainImpl.java:56)[inlined]
                at weblogic/servlet/internal/WebAppServletContext$ServletInvocationAction.wrapRun(Lweblogic/servlet/internal/ServletStubImpl;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)Ljava/lang/Object;(Unknown Source)[inlined]
                at weblogic/servlet/internal/WebAppServletContext$ServletInvocationAction.run()Ljava/lang/Object;(Unknown Source)[optimized]
                at weblogic/security/acl/internal/AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)[optimized]
                at weblogic/security/service/SecurityManager.runAs(SecurityManager.java:120)[inlined]
                at weblogic/servlet/internal/WebAppServletContext.securedExecute(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Z)V(Unknown Source)[inlined]
                at weblogic/servlet/internal/WebAppServletContext.execute(Lweblogic/servlet/internal/ServletRequestImpl;Lweblogic/servlet/internal/ServletResponseImpl;)V(Unknown Source)[optimized]
                at weblogic/servlet/internal/ServletRequestImpl.run()V(Unknown Source)[optimized]
                at weblogic/work/ExecuteThread.execute(ExecuteThread.java:209)[inlined]
                at weblogic/work/ExecuteThread.run(ExecuteThread.java:178)[optimized]
                at jrockit/vm/RNI.c2java(JJJJJ)V(Native Method)

Now here are the lookup threads waiting on the lock [under load you could have literally hundreds as in our case]:

[ACTIVE] ExecuteThread: '146' for queue: 'weblogic.kernel.Default (self-tuning)'" id=8923 idx=0x300 tid=30008 prio=5 alive, blocked, native_blocked, daemon
                -- Blocked trying to get lock: java/util/HashMap@0x10d49e228[fat lock]
                at jrockit/vm/Threads.waitForUnblockSignal()V(Native Method)
                at jrockit/vm/Locks.fatLockBlockOrSpin(Locks.java:1411)[optimized]
                at jrockit/vm/Locks.lockFat(Locks.java:1512)[optimized]
                at jrockit/vm/Locks.monitorEnterSecondStageHard(Locks.java:1054)[optimized]
                at jrockit/vm/Locks.monitorEnterSecondStage(Locks.java:1005)[optimized]
                at org/springframework/context/support/ReloadableResourceBundleMessageSource.getProperties(ReloadableResourceBundleMessageSource.java:431)[inlined]
                at org/springframework/context/support/ReloadableResourceBundleMessageSource.resolveCodeWithoutArguments(ReloadableResourceBundleMessageSource.java:272)[optimized]
                at org/springframework/context/support/AbstractMessageSource.getMessageInternal(AbstractMessageSource.java:193)[inlined]
                at org/springframework/context/support/AbstractMessageSource.getMessage(AbstractMessageSource.java:127)[optimized]
                at org/springframework/context/support/AbstractApplicationContext.getMessage(AbstractApplicationContext.java:1210)[optimized]
                at org/springframework/web/servlet/tags/MessageTag.resolveMessage(MessageTag.java:227)[inlined]
                at org/springframework/web/servlet/tags/MessageTag.doStartTagInternal(MessageTag.java:165)[optimized]
                at org/springframework/web/servlet/tags/RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79)[optimized]
                at jsp_servlet/_web_45_inf/_views/__viewpaymentsalerts._jsp__tag34(__viewpaymentsalerts.java:2695)
                at jsp_servlet/_web_45_inf/_views/__viewpaymentsalerts._jsp__tag30(__viewpaymentsalerts.java:2523)
                at jsp_servlet/_web_45_inf/_views/__viewpaymentsalerts._jspService(__viewpaymentsalerts.java:601)
                at weblogic/servlet/jsp/JspBase.service(JspBase.java:34)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)[inlined]
                at weblogic/servlet/internal/ServletStubImpl.execute(ServletStubImpl.java:300)[optimized]
                at weblogic/servlet/internal/ServletStubImpl.execute(ServletStubImpl.java:183)[inlined]
                at weblogic/servlet/internal/RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:523)[optimized]
                at weblogic/servlet/internal/RequestDispatcherImpl.forward(RequestDispatcherImpl.java:253)[optimized]
                at org/springframework/web/servlet/view/InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)[optimized]
                at org/springframework/web/servlet/view/AbstractView.render(AbstractView.java:262)[optimized]
                at org/springframework/web/servlet/DispatcherServlet.render(DispatcherServlet.java:1157)[optimized]
                at org/springframework/web/servlet/DispatcherServlet.doDispatch(DispatcherServlet.java:927)[optimized]
                at org/springframework/web/servlet/DispatcherServlet.doService(DispatcherServlet.java:827)[inlined]
                at org/springframework/web/servlet/FrameworkServlet.processRequest(FrameworkServlet.java:882)[inlined]
                at org/springframework/web/servlet/FrameworkServlet.doGet(FrameworkServlet.java:778)[optimized]
                at javax/servlet/http/HttpServlet.service(HttpServlet.java:707)[optimized]
                at javax/servlet/http/HttpServlet.service(HttpServlet.java:820)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)[optimized]
                at weblogic/servlet/internal/StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)[inlined]
                at weblogic/servlet/internal/ServletStubImpl.execute(ServletStubImpl.java:300)[optimized]
                at weblogic/servlet/internal/TailFilter.doFilter(TailFilter.java:26)[optimized]
                at weblogic/servlet/internal/FilterChainImpl.doFilter(FilterChainImpl.java:56)[optimized]
                at com/capitalone/epf/context/filters/EPFContextServletFilter.doFilter(EPFContextServletFilter.java:89)[optimized]
                at weblogic/servlet/internal/FilterChainImpl.doFilter(FilterChainImpl.java:56)[inlined]
                at weblogic/servlet/internal/WebAppServletContext$ServletInvocationAction.wrapRun(Lweblogic/servlet/internal/ServletStubImpl;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)Ljava/lang/Object;(Unknown Source)[inlined]
                at weblogic/servlet/internal/WebAppServletContext$ServletInvocationAction.run()Ljava/lang/Object;(Unknown Source)[optimized]
                at weblogic/security/acl/internal/AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)[optimized]
                at weblogic/security/service/SecurityManager.runAs(SecurityManager.java:120)[inlined]
                at weblogic/servlet/internal/WebAppServletContext.securedExecute(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Z)V(Unknown Source)[inlined]
                at weblogic/servlet/internal/WebAppServletContext.execute(Lweblogic/servlet/internal/ServletRequestImpl;Lweblogic/servlet/internal/ServletResponseImpl;)V(Unknown Source)[optimized]
                at weblogic/servlet/internal/ServletRequestImpl.run()V(Unknown Source)[optimized]
                at weblogic/work/ExecuteThread.execute(ExecuteThread.java:209)[inlined]
                at weblogic/work/ExecuteThread.run(ExecuteThread.java:178)[optimized]
                at jrockit/vm/RNI.c2java(JJJJJ)V(Native Method)

Affects: 3.1 GA

Attachments:

Issue Links:

Referenced from: commits a000dd7

7 votes, 6 watchers

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions