This is an automated email from the ASF dual-hosted git repository. srichter pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/flink.git
commit 1a10fbef644ad32a3358711bfa5a167118186482 Author: Stefan Richter <s.rich...@data-artisans.com> AuthorDate: Thu Mar 14 14:50:18 2019 +0100 [FLINK-11952][1/3] Make ChildFirstClassLoader a top-level class in flink-core --- .../apache/flink/util/ChildFirstClassLoader.java | 123 +++++++++++++++++++++ .../librarycache/FlinkUserCodeClassLoaders.java | 103 +---------------- 2 files changed, 125 insertions(+), 101 deletions(-) diff --git a/flink-core/src/main/java/org/apache/flink/util/ChildFirstClassLoader.java b/flink-core/src/main/java/org/apache/flink/util/ChildFirstClassLoader.java new file mode 100644 index 0000000..3942b1b --- /dev/null +++ b/flink-core/src/main/java/org/apache/flink/util/ChildFirstClassLoader.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.flink.util; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +/** + * A variant of the URLClassLoader that first loads from the URLs and only after that from the parent. + * + * <p>{@link #getResourceAsStream(String)} uses {@link #getResource(String)} internally so we + * don't override that. + */ +public final class ChildFirstClassLoader extends URLClassLoader { + + /** + * The classes that should always go through the parent ClassLoader. This is relevant + * for Flink classes, for example, to avoid loading Flink classes that cross the + * user-code/system-code barrier in the user-code ClassLoader. + */ + private final String[] alwaysParentFirstPatterns; + + public ChildFirstClassLoader(URL[] urls, ClassLoader parent, String[] alwaysParentFirstPatterns) { + super(urls, parent); + this.alwaysParentFirstPatterns = alwaysParentFirstPatterns; + } + + @Override + protected synchronized Class<?> loadClass( + String name, boolean resolve) throws ClassNotFoundException { + + // First, check if the class has already been loaded + Class<?> c = findLoadedClass(name); + + if (c == null) { + // check whether the class should go parent-first + for (String alwaysParentFirstPattern : alwaysParentFirstPatterns) { + if (name.startsWith(alwaysParentFirstPattern)) { + return super.loadClass(name, resolve); + } + } + + try { + // check the URLs + c = findClass(name); + } catch (ClassNotFoundException e) { + // let URLClassLoader do it, which will eventually call the parent + c = super.loadClass(name, resolve); + } + } + + if (resolve) { + resolveClass(c); + } + + return c; + } + + @Override + public URL getResource(String name) { + // first, try and find it via the URLClassloader + URL urlClassLoaderResource = findResource(name); + + if (urlClassLoaderResource != null) { + return urlClassLoaderResource; + } + + // delegate to super + return super.getResource(name); + } + + @Override + public Enumeration<URL> getResources(String name) throws IOException { + // first get resources from URLClassloader + Enumeration<URL> urlClassLoaderResources = findResources(name); + + final List<URL> result = new ArrayList<>(); + + while (urlClassLoaderResources.hasMoreElements()) { + result.add(urlClassLoaderResources.nextElement()); + } + + // get parent urls + Enumeration<URL> parentResources = getParent().getResources(name); + + while (parentResources.hasMoreElements()) { + result.add(parentResources.nextElement()); + } + + return new Enumeration<URL>() { + Iterator<URL> iter = result.iterator(); + + public boolean hasMoreElements() { + return iter.hasNext(); + } + + public URL nextElement() { + return iter.next(); + } + }; + } +} diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/execution/librarycache/FlinkUserCodeClassLoaders.java b/flink-runtime/src/main/java/org/apache/flink/runtime/execution/librarycache/FlinkUserCodeClassLoaders.java index a18bd6a..0df7c7a 100644 --- a/flink-runtime/src/main/java/org/apache/flink/runtime/execution/librarycache/FlinkUserCodeClassLoaders.java +++ b/flink-runtime/src/main/java/org/apache/flink/runtime/execution/librarycache/FlinkUserCodeClassLoaders.java @@ -18,13 +18,10 @@ package org.apache.flink.runtime.execution.librarycache; -import java.io.IOException; +import org.apache.flink.util.ChildFirstClassLoader; + import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; /** * Gives the URLClassLoader a nicer name for debugging purposes. @@ -85,100 +82,4 @@ public class FlinkUserCodeClassLoaders { super(urls, parent); } } - - /** - * A variant of the URLClassLoader that first loads from the URLs and only after that from the parent. - * - * <p>{@link #getResourceAsStream(String)} uses {@link #getResource(String)} internally so we - * don't override that. - */ - static final class ChildFirstClassLoader extends URLClassLoader { - - /** - * The classes that should always go through the parent ClassLoader. This is relevant - * for Flink classes, for example, to avoid loading Flink classes that cross the - * user-code/system-code barrier in the user-code ClassLoader. - */ - private final String[] alwaysParentFirstPatterns; - - public ChildFirstClassLoader(URL[] urls, ClassLoader parent, String[] alwaysParentFirstPatterns) { - super(urls, parent); - this.alwaysParentFirstPatterns = alwaysParentFirstPatterns; - } - - @Override - protected synchronized Class<?> loadClass( - String name, boolean resolve) throws ClassNotFoundException { - - // First, check if the class has already been loaded - Class<?> c = findLoadedClass(name); - - if (c == null) { - // check whether the class should go parent-first - for (String alwaysParentFirstPattern : alwaysParentFirstPatterns) { - if (name.startsWith(alwaysParentFirstPattern)) { - return super.loadClass(name, resolve); - } - } - - try { - // check the URLs - c = findClass(name); - } catch (ClassNotFoundException e) { - // let URLClassLoader do it, which will eventually call the parent - c = super.loadClass(name, resolve); - } - } - - if (resolve) { - resolveClass(c); - } - - return c; - } - - @Override - public URL getResource(String name) { - // first, try and find it via the URLClassloader - URL urlClassLoaderResource = findResource(name); - - if (urlClassLoaderResource != null) { - return urlClassLoaderResource; - } - - // delegate to super - return super.getResource(name); - } - - @Override - public Enumeration<URL> getResources(String name) throws IOException { - // first get resources from URLClassloader - Enumeration<URL> urlClassLoaderResources = findResources(name); - - final List<URL> result = new ArrayList<>(); - - while (urlClassLoaderResources.hasMoreElements()) { - result.add(urlClassLoaderResources.nextElement()); - } - - // get parent urls - Enumeration<URL> parentResources = getParent().getResources(name); - - while (parentResources.hasMoreElements()) { - result.add(parentResources.nextElement()); - } - - return new Enumeration<URL>() { - Iterator<URL> iter = result.iterator(); - - public boolean hasMoreElements() { - return iter.hasNext(); - } - - public URL nextElement() { - return iter.next(); - } - }; - } - } }