Classloader interop improvements (#1480)

This commit is contained in:
Michiel Borkent 2023-02-03 13:08:55 +01:00 committed by GitHub
parent 72dbf53df7
commit ca1e2d7769
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 150 additions and 17 deletions

View file

@ -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"}

View file

@ -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))

View file

@ -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;
}
} }

View file

@ -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"]

View file

@ -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"}

View 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);
}
}

View file

@ -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 .

View file

@ -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

View file

@ -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)))))