Skip to content

Commit

Permalink
Merge pull request #539 from tobias/java-9-support
Browse files Browse the repository at this point in the history
Improvements to work with Java 9
  • Loading branch information
alandipert authored Dec 13, 2016
2 parents 03d60a9 + a046a49 commit aa53989
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 12 deletions.
14 changes: 14 additions & 0 deletions boot/base/src/main/java/boot/AddableClassLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package boot;

import java.net.URL;
import java.net.URLClassLoader;

// Allows us to have a modifiable ClassLoader without having to call
// .setAccessible on URLClassLoader.addURL(), since that's not allowed
// by default under Java 9
public class AddableClassLoader extends URLClassLoader {
public AddableClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent); }

public void addURL(URL url) {
super.addURL(url); }}
4 changes: 2 additions & 2 deletions boot/base/src/main/java/boot/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.nio.channels.FileChannel;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
import java.util.Date;
import java.util.UUID;
Expand Down Expand Up @@ -306,7 +305,7 @@ public class App {

for (int i=0; i<jarFiles.length; i++) urls[i] = jarFiles[i].toURI().toURL();

ClassLoader cl = new URLClassLoader(urls, App.class.getClassLoader());
ClassLoader cl = new AddableClassLoader(urls, App.class.getClassLoader());
ClojureRuntimeShim rt = ClojureRuntimeShim.newRuntime(cl);

rt.setName(name != null ? name : "anonymous");
Expand All @@ -319,6 +318,7 @@ public class App {

rt.require("boot.pod");
rt.invoke("boot.pod/seal-app-classloader");
rt.invoke("boot.pod/extend-addable-classloader");
rt.invoke("boot.pod/set-data!", data);
rt.invoke("boot.pod/set-pods!", pods);
rt.invoke("boot.pod/set-this-pod!", new WeakReference<ClojureRuntimeShim>(rt));
Expand Down
2 changes: 1 addition & 1 deletion boot/pod/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[boot/base ~version :scope "provided"]
[org.clojure/clojure "1.6.0" :scope "provided"]
[org.tcrawley/dynapath "0.2.4" :scope "compile"]
[org.tcrawley/dynapath "0.2.5" :scope "compile"]
[org.projectodd.shimdandy/shimdandy-impl "1.2.0" :scope "compile"]])
49 changes: 40 additions & 9 deletions boot/pod/src/boot/pod.clj
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,32 @@
(let [[group artifact] ((juxt namespace name) sym)]
[(or group artifact) artifact]))

(defn extend-addable-classloader
"Opens up the class loader used to create the shim for
modification. Once seal-app-classloader is called, this will be the
highest class loader user code can modify.
This function is called during Boot's bootstrapping phase, and shouldn't
be needed in client code under normal circumstances."
[]
(extend boot.AddableClassLoader
cp/DynamicClasspath
(assoc dynapath.dynamic-classpath/base-readable-addable-classpath
:classpath-urls #(seq (.getURLs %))
:add-classpath-url #(.addURL %1 %2))))

(def sealed-classloader-fns
(assoc cp/base-readable-addable-classpath
:classpath-urls #(seq (.getURLs %))
:can-add? (constantly false)))

(defn seal-app-classloader
"Implements the DynamicClasspath protocol to the AppClassLoader class such
that instances of this class will refuse attempts at runtime modification
by libraries that do so via dynapath[1]. The system class loader is of the
type AppClassLoader.
"Implements the DynamicClasspath protocol to the AppClassLoader and
boot's ParentClassLoader classes such that instances of those
classes will refuse attempts at runtime modification by libraries
that do so via dynapath[1]. The system class loader is of the type
AppClassLoader under Java < 9, and the top-level class loader used
by boot is a ParentClassLoader.
The purpose of this is to ensure that Clojure libraries do not pollute the
higher-level class loaders with classes and interfaces created dynamically
Expand All @@ -42,11 +63,21 @@
[1]: https://github.com/tobias/dynapath
[2]: https://github.com/clojure-emacs/cider-nrepl/blob/36333cae25fd510747321f86e2f0369fcb7b4afd/README.md#with-jboss-asjboss-eapwildfly"
[]
(extend sun.misc.Launcher$AppClassLoader
cp/DynamicClasspath
(assoc cp/base-readable-addable-classpath
:classpath-urls #(seq (.getURLs %))
:can-add? (constantly false))))
(try
;; this import will fail if the user doesn't have a new enough boot.sh
(import boot.bin.ParentClassLoader)
(eval '(extend boot.bin.ParentClassLoader
dynapath.dynamic-classpath/DynamicClasspath
boot.pod/sealed-classloader-fns))
(catch Exception _))

(try
;; this import will fail if the user is using Java 9
(import sun.misc.Launcher$AppClassLoader)
(eval '(extend sun.misc.Launcher$AppClassLoader
dynapath.dynamic-classpath/DynamicClasspath
boot.pod/sealed-classloader-fns))
(catch Exception _)))

(defn ^{:boot/from :cemerick/pomegranate} classloader-hierarchy
"Returns a seq of classloaders, with the tip of the hierarchy first.
Expand Down

0 comments on commit aa53989

Please sign in to comment.