Classloader interop improvements (#1480)
This commit is contained in:
parent
72dbf53df7
commit
ca1e2d7769
9 changed files with 150 additions and 17 deletions
2
deps.edn
2
deps.edn
|
|
@ -20,7 +20,7 @@
|
||||||
"impl-java/src"],
|
"impl-java/src"],
|
||||||
:deps {org.clojure/clojure {:mvn/version "1.11.1"},
|
:deps {org.clojure/clojure {:mvn/version "1.11.1"},
|
||||||
org.babashka/sci {:local/root "sci"}
|
org.babashka/sci {:local/root "sci"}
|
||||||
org.babashka/babashka.impl.java {:mvn/version "0.1.6"}
|
org.babashka/babashka.impl.java {:mvn/version "0.1.8"}
|
||||||
org.babashka/sci.impl.types {:mvn/version "0.0.2"}
|
org.babashka/sci.impl.types {:mvn/version "0.0.2"}
|
||||||
babashka/babashka.curl {:local/root "babashka.curl"}
|
babashka/babashka.curl {:local/root "babashka.curl"}
|
||||||
babashka/fs {:local/root "fs"}
|
babashka/fs {:local/root "fs"}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
[clojure.tools.build.api :as b]))
|
[clojure.tools.build.api :as b]))
|
||||||
|
|
||||||
(def lib 'org.babashka/babashka.impl.java)
|
(def lib 'org.babashka/babashka.impl.java)
|
||||||
(def version "0.1.6")
|
(def version "0.1.8")
|
||||||
(def class-dir "target/classes")
|
(def class-dir "target/classes")
|
||||||
(def basis (b/create-basis {:project "deps.edn"}))
|
(def basis (b/create-basis {:project "deps.edn"}))
|
||||||
(def jar-file (format "target/%s-%s.jar" (name lib) version))
|
(def jar-file (format "target/%s-%s.jar" (name lib) version))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
|
// This file is mostly a workaround for https://github.com/oracle/graal/issues/1956
|
||||||
|
|
||||||
package babashka.impl;
|
package babashka.impl;
|
||||||
|
|
||||||
public class URLClassLoader extends java.net.URLClassLoader {
|
import java.util.WeakHashMap;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.jar.*;
|
||||||
|
|
||||||
|
public class URLClassLoader extends java.net.URLClassLoader implements Closeable {
|
||||||
|
|
||||||
|
private WeakHashMap<Closeable,Void>
|
||||||
|
closeables = new WeakHashMap<>();
|
||||||
|
|
||||||
public URLClassLoader(java.net.URL[] urls) {
|
public URLClassLoader(java.net.URL[] urls) {
|
||||||
super(urls);
|
super(urls);
|
||||||
|
|
@ -13,4 +24,71 @@ public class URLClassLoader extends java.net.URLClassLoader {
|
||||||
public void _addURL(java.net.URL url) {
|
public void _addURL(java.net.URL url) {
|
||||||
super.addURL(url);
|
super.addURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calling super.getResource() returned nil in native-image
|
||||||
|
public java.net.URL getResource(String name) {
|
||||||
|
return findResource(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calling super.getResourceAsStream() returned nil in native-image
|
||||||
|
public InputStream getResourceAsStream(String name) {
|
||||||
|
Objects.requireNonNull(name);
|
||||||
|
URL url = getResource(name);
|
||||||
|
try {
|
||||||
|
if (url == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
URLConnection urlc = url.openConnection();
|
||||||
|
InputStream is = urlc.getInputStream();
|
||||||
|
if (urlc instanceof JarURLConnection) {
|
||||||
|
JarFile jar = ((JarURLConnection)urlc).getJarFile();
|
||||||
|
synchronized (closeables) {
|
||||||
|
if (!closeables.containsKey(jar)) {
|
||||||
|
closeables.put(jar, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
synchronized (closeables) {
|
||||||
|
closeables.put(is, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return is;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.Enumeration<java.net.URL> getResources(String name) throws java.io.IOException {
|
||||||
|
return findResources(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
super.close();
|
||||||
|
|
||||||
|
java.util.List<IOException> errors = new java.util.ArrayList<IOException>();
|
||||||
|
|
||||||
|
synchronized (closeables) {
|
||||||
|
java.util.Set<Closeable> keys = closeables.keySet();
|
||||||
|
for (Closeable c : keys) {
|
||||||
|
try {
|
||||||
|
c.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
errors.add(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closeables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOException firstEx = errors.remove(0);
|
||||||
|
|
||||||
|
for (IOException error: errors) {
|
||||||
|
firstEx.addSuppressed(error);
|
||||||
|
}
|
||||||
|
throw firstEx;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
[nrepl/bencode "1.1.0"]
|
[nrepl/bencode "1.1.0"]
|
||||||
[borkdude/sci.impl.reflector "0.0.1"]
|
[borkdude/sci.impl.reflector "0.0.1"]
|
||||||
[org.babashka/sci.impl.types "0.0.2"]
|
[org.babashka/sci.impl.types "0.0.2"]
|
||||||
[org.babashka/babashka.impl.java "0.1.6"]
|
[org.babashka/babashka.impl.java "0.1.8"]
|
||||||
[org.clojure/core.async "1.6.673"]
|
[org.clojure/core.async "1.6.673"]
|
||||||
[org.clojure/test.check "1.1.1"]
|
[org.clojure/test.check "1.1.1"]
|
||||||
[com.github.clj-easy/graal-build-time "0.1.0"]
|
[com.github.clj-easy/graal-build-time "0.1.0"]
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"impl-java/src"],
|
"impl-java/src"],
|
||||||
:deps {org.clojure/clojure {:mvn/version "1.11.1"},
|
:deps {org.clojure/clojure {:mvn/version "1.11.1"},
|
||||||
org.babashka/sci {:local/root "sci"}
|
org.babashka/sci {:local/root "sci"}
|
||||||
org.babashka/babashka.impl.java {:mvn/version "0.1.6"}
|
org.babashka/babashka.impl.java {:mvn/version "0.1.8"}
|
||||||
org.babashka/sci.impl.types {:mvn/version "0.0.2"}
|
org.babashka/sci.impl.types {:mvn/version "0.0.2"}
|
||||||
babashka/babashka.curl {:local/root "babashka.curl"}
|
babashka/babashka.curl {:local/root "babashka.curl"}
|
||||||
babashka/fs {:local/root "fs"}
|
babashka/fs {:local/root "fs"}
|
||||||
|
|
|
||||||
55
resources/UrlClassLoaderSubstitutions.java
Normal file
55
resources/UrlClassLoaderSubstitutions.java
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import com.oracle.svm.core.annotate.Alias;
|
||||||
|
import com.oracle.svm.core.annotate.RecomputeFieldValue;
|
||||||
|
import com.oracle.svm.core.annotate.Substitute;
|
||||||
|
import com.oracle.svm.core.annotate.TargetClass;
|
||||||
|
|
||||||
|
@TargetClass(URLClassLoader.class)
|
||||||
|
@SuppressWarnings({"unused", "static-method"})
|
||||||
|
final class Target_java_net_URLClassLoader {
|
||||||
|
@Alias//
|
||||||
|
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClass = WeakHashMap.class)//
|
||||||
|
private WeakHashMap<Closeable, Void> closeables;
|
||||||
|
|
||||||
|
@Substitute
|
||||||
|
public InputStream getResourceAsStream(String name) throws IOException {
|
||||||
|
System.out.println("getResource");
|
||||||
|
return null;
|
||||||
|
// return Resources.createInputStream(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,17 +26,6 @@ fi
|
||||||
export JAVA_HOME=$GRAALVM_HOME
|
export JAVA_HOME=$GRAALVM_HOME
|
||||||
export PATH=$GRAALVM_HOME/bin:$PATH
|
export PATH=$GRAALVM_HOME/bin:$PATH
|
||||||
|
|
||||||
rm -rf resources/*.class
|
|
||||||
# SVM_JAR=$(find -L "$GRAALVM_HOME" | grep svm.jar)
|
|
||||||
# "$GRAALVM_HOME/bin/javac" -cp "$SVM_JAR" resources/CutOffCoreServicesDependencies.java
|
|
||||||
# "$GRAALVM_HOME/bin/javac" -cp "$SVM_JAR" resources/CutOffSunAwtWwwContentAudioAiff.java
|
|
||||||
# "$GRAALVM_HOME/bin/javac" -cp "$SVM_JAR" resources/CutOffMisc.java
|
|
||||||
if [ -z "$BABASHKA_JAR" ]; then
|
|
||||||
lein with-profiles +reflection,+native-image "do" run
|
|
||||||
lein "do" clean, uberjar, metabom
|
|
||||||
BABASHKA_JAR=${BABASHKA_JAR:-"target/babashka-$BABASHKA_VERSION-standalone.jar"}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# because script/test cleans target during ci before the jar can we saved
|
# because script/test cleans target during ci before the jar can we saved
|
||||||
cp target/metabom.jar .
|
cp target/metabom.jar .
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,12 @@ fi
|
||||||
mkdir -p resources/META-INF/babashka
|
mkdir -p resources/META-INF/babashka
|
||||||
cp deps.edn resources/META-INF/babashka/deps.edn
|
cp deps.edn resources/META-INF/babashka/deps.edn
|
||||||
|
|
||||||
|
rm -rf resources/*.class
|
||||||
|
# SVM_JAR=$(find -L "$GRAALVM_HOME" | grep svm.jar)
|
||||||
|
# "$GRAALVM_HOME/bin/javac" -cp "$SVM_JAR" resources/UrlClassLoaderSubstitutions.java
|
||||||
|
# "$GRAALVM_HOME/bin/javac" -cp "$SVM_JAR" resources/CutOffSunAwtWwwContentAudioAiff.java
|
||||||
|
# "$GRAALVM_HOME/bin/javac" -cp "$SVM_JAR" resources/CutOffMisc.java
|
||||||
|
|
||||||
if [ -z "$BABASHKA_JAR" ]; then
|
if [ -z "$BABASHKA_JAR" ]; then
|
||||||
lein with-profiles "$BABASHKA_LEIN_PROFILES,+reflection,-uberjar" do run
|
lein with-profiles "$BABASHKA_LEIN_PROFILES,+reflection,-uberjar" do run
|
||||||
lein with-profiles "$BABASHKA_LEIN_PROFILES" do clean, uberjar, metabom
|
lein with-profiles "$BABASHKA_LEIN_PROFILES" do clean, uberjar, metabom
|
||||||
|
|
|
||||||
|
|
@ -76,4 +76,9 @@
|
||||||
(tu/bb nil "--classpath" "test-resources/babashka/src_for_classpath_test/foo.jar"
|
(tu/bb nil "--classpath" "test-resources/babashka/src_for_classpath_test/foo.jar"
|
||||||
"(first (map str (.getURLs (clojure.lang.RT/baseLoader))))")]
|
"(first (map str (.getURLs (clojure.lang.RT/baseLoader))))")]
|
||||||
(is (str/includes? url "file:"))
|
(is (str/includes? url "file:"))
|
||||||
(is (str/includes? url "foo.jar"))))
|
(is (str/includes? url "foo.jar")))
|
||||||
|
(let [results (tu/bb nil "--classpath" "test-resources/babashka/src_for_classpath_test/foo.jar"
|
||||||
|
"(map some? [(.getResource (clojure.lang.RT/baseLoader) \"foo.clj\")
|
||||||
|
(.getResourceAsStream (clojure.lang.RT/baseLoader) \"foo.clj\")
|
||||||
|
(.getResources (clojure.lang.RT/baseLoader) \"foo.clj\")])")]
|
||||||
|
(is (= [true true true] (edn/read-string results)))))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue