[ https://issues.apache.org/jira/browse/FELIX-5759?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Karl Pauls reassigned FELIX-5759: --------------------------------- Assignee: Karl Pauls > StackOverflowError thrown during URL construction > ------------------------------------------------- > > Key: FELIX-5759 > URL: https://issues.apache.org/jira/browse/FELIX-5759 > Project: Felix > Issue Type: Bug > Reporter: Ali Kamali > Assignee: Karl Pauls > Priority: Critical > > I get the following callstack resulting in a stack overflow error when > building a URL object: > {code} > [info] at > org.apache.felix.framework.URLHandlersStreamHandlerProxy.parseURL(URLHandlersStreamHandlerProxy.java:401) > [info] at java.net.URL.<init>(URL.java:622) > [info] at java.net.URL.<init>(URL.java:490) > [info] at > org.apache.felix.framework.URLHandlersStreamHandlerProxy.parseURL(URLHandlersStreamHandlerProxy.java:401) > [info] at java.net.URL.<init>(URL.java:622) > [info] at java.net.URL.<init>(URL.java:490) > [info] at > org.apache.felix.framework.URLHandlersStreamHandlerProxy.parseURL(URLHandlersStreamHandlerProxy.java:401) > [info] at java.net.URL.<init>(URL.java:622) > [info] at java.net.URL.<init>(URL.java:490) > [info] at > org.apache.felix.framework.URLHandlersStreamHandlerProxy.parseURL(URLHandlersStreamHandlerProxy.java:401) > [info] at java.net.URL.<init>(URL.java:622) > [info] at java.net.URL.<init>(URL.java:490) > [info] at > org.apache.felix.framework.URLHandlersStreamHandlerProxy.parseURL(URLHandlersStreamHandlerProxy.java:401) > [info] at java.net.URL.<init>(URL.java:622) > [info] at java.net.URL.<init>(URL.java:490) > [info] at > org.apache.felix.framework.URLHandlersStreamHandlerProxy.parseURL(URLHandlersStreamHandlerProxy.java:401) > [info] at java.net.URL.<init>(URL.java:622) > [info] at java.net.URL.<init>(URL.java:490) > [info] at > org.apache.felix.framework.URLHandlersStreamHandlerProxy.parseURL(URLHandlersStreamHandlerProxy.java:401) > {code} > Using org.apache.felix.framework 4.4.1 and Java 1.8.0_111 running on Ubuntu. > We started getting this exception after upgrading to Spark 2.2.0, after some > investigation we realized Spark 2.2.0 registers its own > {{URLStreamHandlerFactory}}: > {code} > package org.apache.spark.sql.internal > object SharedState extends Logging { > try { > URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()) > } catch { > case e: Error => > logWarning("URL.setURLStreamHandlerFactory failed to set > FsUrlStreamHandlerFactory") > } > ... > {code} > Looks like the bug is related to line 128 in {{URLHandlers.java}}: > {code} > URLStreamHandler handler = getBuiltInStreamHandler(protocol, > factory); > if (handler != null) > { > URL url = new URL(protocol, null, -1, "", handler); > m_handlerToURL.put(handler, url); > } > {code} > This code assumes there is a unique mapping from handlers to protocols, which > doesn't seem to be a valid assumption, at least not with Spark. Spark URL > handler factory is returning the same handler instance for both {{file}} and > {{ftp}} protocols. When {{URLHandlers}} is initializing it first tries to > register a handler for {{file}} and then for {{ftp}}, but because the factory > returns the same handler we end up replacing the URL object we have for > {{file}} with {{ftp}} in {{m_handlerToURL}}. > Later when a URL is being constructed it calls {{createURLStreamHandler}} > from URLHandlers, at the end of this method: > {code} > // If built-in content handler, then create a proxy handler. > return addToStreamCache(protocol, > new URLHandlersStreamHandlerProxy(protocol, m_secureAction, > handler, (URL) m_handlerToURL.get(handler))); > {code} > Note that it's trying to use {{m_handlerToURL}} to look up the protocol for > the handler, and in case of {{file}} instead of returning a URL with protocol > set to {{file}} it returns a URL with protocol set to {{ftp}}, so > {{URLHandlersStreamHandlerProxy}} gets constructed with {{m_builtInURL}} set > to {{ftp}}. > Later in URL.java we have this code: > {code} > if ((context != null) && ((newProtocol == null) || > newProtocol.equalsIgnoreCase(context.protocol))) { > // inherit the protocol handler from the context > // if not specified to the constructor > if (handler == null) { > handler = context.handler; > } > {code} > This code only uses the handler if protocols match, but in this case > protocols don't match because it's expected to be {{file}} but we receive > {{ftp}} that comes from {{m_builtInURL}}, and the code falls back to asking > the factory to create a new handler: > {code} > if (handler == null && > (handler = getURLStreamHandler(protocol)) == null) { > throw new MalformedURLException("unknown protocol: > "+protocol); > } > {code} > The factory returns a handler with protocol set to {{ftp}} again and we get > stuck in a loop. > Looking at the newest Felix code looks like the assumption of having a unique > handler per protocol is still there, so I believe this bug still exists in > the newest Felix as well. > To reproduce this bug before starting a bundle you only need to register a > factory that returns the same handler instance for {{file}} and {{ftp}}. -- This message was sent by Atlassian JIRA (v6.4.14#64029)