From 522a7a2995a2f2f391e40cacd5127500e7c55d1b Mon Sep 17 00:00:00 2001 From: Sam Umbach Date: Mon, 24 Mar 2025 20:32:16 -0400 Subject: [PATCH 1/3] Correct minor technical errors --- _clojure_jvm/02_basic_java.md | 2 +- _clojure_jvm/03_class_files.md | 8 ++++---- _clojure_jvm/04_jar_files.md | 6 +++--- _clojure_jvm/05_dependencies.md | 3 ++- _clojure_jvm/06_common_issues.md | 6 +++--- _clojure_jvm/07_evaluating_clojure.md | 2 +- _clojure_jvm/08_compiling_clojure.md | 4 ++-- _clojure_jvm/09_deps.md | 6 +++--- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/_clojure_jvm/02_basic_java.md b/_clojure_jvm/02_basic_java.md index 252c185..bb2ae33 100644 --- a/_clojure_jvm/02_basic_java.md +++ b/_clojure_jvm/02_basic_java.md @@ -67,7 +67,7 @@ on the classpath. This can be done with the `-classpath` option to the `java` co change back to the parent directory where the `Hello.java` file is defined - $ cd + $ cd .. ### System classes diff --git a/_clojure_jvm/03_class_files.md b/_clojure_jvm/03_class_files.md index e59c523..eca77c5 100644 --- a/_clojure_jvm/03_class_files.md +++ b/_clojure_jvm/03_class_files.md @@ -106,7 +106,7 @@ Methods which return a value use the grammar for field descriptors to denote the Method descriptors consist of a literal `(`, the corresponding field descriptor for each parameter type in sequence, a literal `)` followed by the return type descriptor. This can be either `V` for `void` methods, or a field descriptor for the return type. -For example the method `public String test(int i, boolean b, Object o)` has a method descriptor of `(IZLjava/lang/Object;)java/lang/String;`. +For example the method `public String test(int i, boolean b, Object o)` has a method descriptor of `(IZLjava/lang/Object;)Ljava/lang/String;`. ## Constant pool contents @@ -118,7 +118,7 @@ Here are the references made by the `test.Hello` class: | #1 | `java/lang/Object::` | Method | Object constructors are given the special name `` within `.class` files. This is invoked by the `test.Hello` constructor (see below). | | #8 | `java/lang/System` | Class | Class which defines the static `out` field | | #7 | `java/lang/System::out` | Field | Reference to the `out` field of the `java.lang.System` class | -| #12 | `Ljava/io/PrintStream` | Type reference | The declared type of the `System.out` field | +| #12 | `Ljava/io/PrintStream;` | Type reference | The declared type of the `System.out` field | | #13 | | String | The string constant "Hello world!" | | #16 | `java/io/PrintStream` | Class | Type defining the `println` method | | #15 | `java/io/PrintStream::println` | Method | The `println` method used to write to the console | @@ -206,7 +206,7 @@ The [getstatic](https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-6.html# `System.out` field within the constant pool of the `test.Hello` class. The literal string "Hello world!" is pushed onto the operand stack with the [ldc](https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-6.html#jvms-6.5.ldc) instruction. The operand of -`#15` is the index of the string within the class constant pool. +`#13` is the index of the string within the class constant pool. -At this point the operand stack contains the arguments to the `java.io.PrintString.` method - the receiver (the contents of the `System.out` field), and the string to write. The +At this point the operand stack contains the arguments to the `java.io.PrintStream.` method - the receiver (the contents of the `System.out` field), and the string to write. The method is invoked with [invokevirtual](https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-6.html#jvms-6.5.invokevirtual) using the method reference in the class constant pool. diff --git a/_clojure_jvm/04_jar_files.md b/_clojure_jvm/04_jar_files.md index 502a2b9..ff7fcbd 100644 --- a/_clojure_jvm/04_jar_files.md +++ b/_clojure_jvm/04_jar_files.md @@ -32,7 +32,7 @@ __src/libhello/MessageSink.java__ In addition, we define a source of messages read from the command-line, and a sink which writes messages a `PrintStream`: -__src/libhello/CommandLinkMessageSource.java__ +__src/libhello/CommandLineMessageSource.java__ ```java {% include code/jar/src/libhello/CommandLineMessageSource.java %} ``` @@ -56,7 +56,7 @@ jar --create --file libhello.jar -C classes/libhello . this creates a `libhello.jar` file in the current directory. We can list the contents of this file with the `--list` command: - jar --lib --file libhello.jar + jar --list --file libhello.jar This shows the archive contains the `.class` files as their expected locations on the classpath, along with a `META-INF/MANIFEST.MF` file. This file is called the `_manifest` file and is described [below](#manifest-files). @@ -163,7 +163,7 @@ We can now build the new JAR: and run it with the `-jar` option as before: - > java --jar echo-uber.jar Hello world '!' + > java -jar echo-uber.jar Hello world '!' ### File collisions diff --git a/_clojure_jvm/05_dependencies.md b/_clojure_jvm/05_dependencies.md index 2b12e1f..cfab433 100644 --- a/_clojure_jvm/05_dependencies.md +++ b/_clojure_jvm/05_dependencies.md @@ -21,7 +21,7 @@ We fetch the JSON library JAR locally and begin work: after a frenetic caffeine-fueled 10-hour coding session, we finally have our new message source implementation: -__JSONMessageSource.java__ +__src/libhello/JSONMessageSource.java__ ``` {% include code/java_dependencies/JSONMessageSource.java %} ``` @@ -171,6 +171,7 @@ json-test/ test/ EchoJSON.java pom.xml + messages.json ``` **pom.xml** diff --git a/_clojure_jvm/06_common_issues.md b/_clojure_jvm/06_common_issues.md index 4266222..0f896dd 100644 --- a/_clojure_jvm/06_common_issues.md +++ b/_clojure_jvm/06_common_issues.md @@ -78,8 +78,8 @@ an application is created which uses the newer version: compiling both class versions and the application against the newer version ``` -pushd version1 && javac Greet.java && popd -pushd version2 && javac Greet.java && popd +pushd version1 && javac Greeter.java && popd +pushd version2 && javac Greeter.java && popd javac -cp .:version2 GreetApp.java ``` @@ -137,7 +137,7 @@ public class MySqlMessageSourceFactory implements MessageSourceFactory { ... } these would then be listed as implementation classes within the corresponding interface service file: -**META-INF/services/com.picosoft.messaging** +**META-INF/services/com.picosoft.messaging.MessageSourceFactory** ``` com.picosoft.messaging.db.PostgresMessageSourceFactory com.picosoft.messaging.db.MySqlMessageSourceFactory diff --git a/_clojure_jvm/07_evaluating_clojure.md b/_clojure_jvm/07_evaluating_clojure.md index fc8f1b3..93e8d01 100644 --- a/_clojure_jvm/07_evaluating_clojure.md +++ b/_clojure_jvm/07_evaluating_clojure.md @@ -37,7 +37,7 @@ classpath the namespace could be defined in. The conversion process is as follow 1. Convert any `.` characters in the namespace name to `/`s 2. Convert any `-` characters in the namespace name to `_`s -3. Add `.clj`, `.cljc` and `.__init.class` to the resulting name +3. Add `.clj`, `.cljc` and `__init.class` to the resulting name This means there are three candidate locations a namespace could be loaded from. Applying the process to the namespace `org.picosoft.lib-hello.core` the candidate locations are: diff --git a/_clojure_jvm/08_compiling_clojure.md b/_clojure_jvm/08_compiling_clojure.md index f03a2a9..520254c 100644 --- a/_clojure_jvm/08_compiling_clojure.md +++ b/_clojure_jvm/08_compiling_clojure.md @@ -89,8 +89,8 @@ The fat JAR can then be built with ``` > mkdir classes uber > unzip -d uber clojure-1.11.1.jar -> unzip -d -o -d uber/ core.specs.alpha-0.2.62.jar -> unzip -d -o -d uber/ spec.alpha-0.3.218.jar +> unzip -o -d uber/ core.specs.alpha-0.2.62.jar +> unzip -o -d uber/ spec.alpha-0.3.218.jar > java -cp clojure-1.11.1.jar:core.specs.alpha-0.2.62.jar:spec.alpha-0.3.218.jar:classes:src clojure.main -e "(compile 'greet.main)" > cp -r classes/* uber/ > cp -r src/* uber/ diff --git a/_clojure_jvm/09_deps.md b/_clojure_jvm/09_deps.md index 895e11a..608fc79 100644 --- a/_clojure_jvm/09_deps.md +++ b/_clojure_jvm/09_deps.md @@ -56,7 +56,7 @@ you can display the computed classpath with ``` > clojure -Spath -src:~/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar:~/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar:... +src:~/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar:... ``` as expected, it contains our `src` directory and the JAR files for the Clojure JAR and all its dependencies. @@ -76,7 +76,7 @@ If you open the first of these (the system project file) you will see it has def **/install/dir/deps.edn** ```clojure -{:path ["src"] +{:paths ["src"] :deps { org.clojure/clojure {:mvn/version "1.11.1"} } @@ -158,7 +158,7 @@ If you look at the classpath for this project: ``` > clojure -Spath -src:~/.gitlibs/libs/clojure/tools.cli/23ee9655fab71cef253a51d1bce3e7b2327499a3/src/main/clojure:~/projects/greet/lib/src +src:~/.gitlibs/libs/clojure/tools.cli/23ee9655fab71cef253a51d1bce3e7b2327499a3/src/main/clojure:...:~/projects/greet/lib/src:... ``` You can see the `tools.cli` repository was cloned locally under `~/.gitlibs` and the local project source directory was placed on the classpath. From 0151447c57ccf4d6783552ae200acc854effb1d5 Mon Sep 17 00:00:00 2001 From: Sam Umbach Date: Mon, 24 Mar 2025 21:16:11 -0400 Subject: [PATCH 2/3] Add Clojure CLI `-M` option to avoid `WARNING: Implicit use of clojure.main with options is deprecated, use -M -m greet.main everyone` --- _clojure_jvm/09_deps.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_clojure_jvm/09_deps.md b/_clojure_jvm/09_deps.md index 608fc79..ffe7df7 100644 --- a/_clojure_jvm/09_deps.md +++ b/_clojure_jvm/09_deps.md @@ -45,10 +45,10 @@ on the classpath since that is where our application namespaces are defined. Def {% include code/deps/basic/src/greet/main.clj %} ``` -The `clojure` CLI allows us to invoke `clojure.main` with the project classpath with the `-m` option: +The `clojure` CLI allows us to invoke `clojure.main` with the project classpath with the `-M` option: ``` -> clojure -m greet.main everyone +> clojure -M -m greet.main everyone Hello everyone! ``` @@ -150,7 +150,7 @@ add it as a Git dependency rather than depend on the published JAR. This results This can then be run as before: ``` -> clojure -m greet.main --excite everyone +> clojure -M -m greet.main --excite everyone Hello everyone! ``` From c1612b9e1d5231ce2335995b07ae147c7c058b9d Mon Sep 17 00:00:00 2001 From: Sam Umbach Date: Mon, 24 Mar 2025 21:07:17 -0400 Subject: [PATCH 3/3] Quote `-cp` argument value in case classpath contains whitespace --- _clojure_jvm/05_dependencies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_clojure_jvm/05_dependencies.md b/_clojure_jvm/05_dependencies.md index cfab433..2cf7100 100644 --- a/_clojure_jvm/05_dependencies.md +++ b/_clojure_jvm/05_dependencies.md @@ -193,7 +193,7 @@ classpath from Maven and supply that to run the application: ``` mvn dependency:build-classpath -Dmdep.outputFile=classpath.txt -java -cp $(cat classpath.txt):target/json-test-1.0.0.jar test.EchoJSON messages.json +java -cp "$(cat classpath.txt):target/json-test-1.0.0.jar" test.EchoJSON messages.json ``` If we look in the `classpath.txt` file written by the `mvn` command we can see it references all transitive dependencies of the application