jgpc42 / insn

Functional JVM bytecode generation for Clojure.
Eclipse Public License 1.0
198 stars 5 forks source link

saving out .class files #6

Closed cnuernber closed 3 years ago

cnuernber commented 3 years ago

Hey, I am working with JDK-16 and I would like to statically generate some classes and load them back via import.

I tried saving the result of get-bytes verbatim into a .class file and the result is the importer thinks the class file is truncated. Do you have an example or any thoughts about this pathway?

I need to be able to save these classes so that I can work with systems such as Graal.

jgpc42 commented 3 years ago

I don't have much experience yet with Graal, but I've got no problems on my end with JDK 16 EAP with bytecode version 16 or the default. Using the write helper fn:

(def test-data
  {:name 'pkg.Main
   ;; :version 16 
   :methods [{:flags [:public :static], :name "main", :desc [[String] :void]
              :emit [[:getstatic System "out"]
                     [:ldc "Hello, World!"]
                     [:invokevirtual java.io.PrintStream "println" [String :void]]
                     [:return]]}]})

(require '[insn.core :as insn])

(insn/write (insn/visit test-data) "/tmp/test")
java -version 2>&1 | grep version
# => openjdk version "14.0.1" 2020-04-14
java -cp /tmp/test pkg.Main
# => Hello, World!

"$jdk16home"/bin/java -version 2>&1 | grep version
# => openjdk version "16-ea" 2021-03-16
"$jdk16home"/bin/java -cp /tmp/test pkg.Main
# => Hello, World!

What do you get when you run the example code above?

jgpc42 commented 3 years ago

No problems when explicitly import-ed either:

(def test-data
  {:name 'pkg2.Test
   ;; :version 16
   :methods [{:flags [:public :static], :name "aux", :desc [:void]
              :emit [[:getstatic System "out"]
                     [:ldc "Hello, World!"]
                     [:invokevirtual java.io.PrintStream "println" [String :void]]
                     [:return]]}]})
package pkg;

import pkg2.Test;

class Main2 {
    public static void main (String[] args) {
        Test.aux();
    }
}
"$jdk16home"/bin/javac -cp /tmp/test pkg/Main2.java
"$jdk16home"/bin/java -cp /tmp/test:. pkg.Main2
# => Hello, World!
cnuernber commented 3 years ago

Ah this is a different pathway. I had (io/copy (byte-input-stream (core/get-bytes class-def)) out-s).

Your solution worked perfectly, thanks!