jacobin - A more than minimal JVM written in Go and capable of running Java 11 bytecode.

Go version Workflow GitHub

jacobin

A more-than-minimal JVM written in Go.

This overview gives the background on this project, including its aspirations and the features that it supports. The remaining pages discuss the basics of JVM operation and, where applicable, how Jacobin implements the various steps, noting any items that would be of particular interest to JVM cognoscenti. I've included references to the official JVM docs, where I can both as a reference for you, the reader, and for the Jacobin team's easy reference.

Status

Intended feature set:

  • Java 11 functionality, but...
  • No JNI (Oracle intends to replace it; see JEP 389)
  • No security manager (Oracle intends to remove it; see JEP 411)
  • No JIT
  • Somewhat less stringent bytecode verification

What we've done so far and what we need to do:

Command-line parsing

  • Gets options from the three environment variables. Details here
  • Parses the command line; identify JVM options and application options
  • Responds to most options listed in the java -help output

To do:

  • Handling JAR files
  • Handling @files (which contain command-line options)
  • Parsing the classpath

Class loading

  • Correctly reads and parses basic classes
  • Extracts bytecode and params needed for execution

To do:

  • Handle more-complex classes
  • Handle interfaces
  • Handle arrays
  • Handle inner classes
  • Automate loading of core Java classes (Object, etc.)

Verification, Linking, Preparation, Initialization

  • Performs integrity check bytecode is correct. ✏️ This is the focus of current coding work

To do:

  • Linking and verification
  • Preparation
  • Initialization

Execution

Not started yet

Garbage Collection

GC is handled by the golang runtime, which has its own GC

Thanks

The overview page carries a right-side panel that expresses our thanks to vendors and programmers who have made the Jacobin project possible. They are many and we are deeply grateful to them.

Owner
Andrew Binstock
Former editor of Oracle's Java Magazine and, earlier, of Dr. Dobb's Journal. Java hacker at heart.
Andrew Binstock
Comments
  • jacobin failed to recognise class file specified by a.b.c

    jacobin failed to recognise class file specified by a.b.c

    Maybe this report is about a feature that is on the jacobin TO-DO list? If so, pardon my jumping the gun.

    Tree-top: scimark2_java, cloned from https://github.com/texadactyl/scimark2_java. ls -R

    .:
    jnt  LICENSE  original_README.txt  README.md
    
    ./jnt:
    Bench  scimark2
    
    ./jnt/Bench:
    Applet.java  Bench.java  Formatter.java  HTTPPost.java  Plotter.java  SendMail.java  Stopwatch.java  SubmitDialog.java  Target.java
    
    ./jnt/scimark2:
    applet.java        commandline.java  Constants.java  FFT.java     kernel.class  LU.class  MonteCarlo.class  Random.class  SOR.class  SparseCompRow.class  Stopwatch.class
    commandline.class  Constants.class   FFT.class       Jacobi.java  kernel.java   LU.java   MonteCarlo.java   Random.java   SOR.java   SparseCompRow.java   Stopwatch.java
    

    Compile: javac -O jnt/scimark2/commandline.java

    Run the original jvm: java jnt.scimark2.commandline

    SciMark 2.0a, elasped time = 27.23s
    URL: https://math.nist.gov/scimark2/index.html
    
    Composite Score: 2901.249182054803
    FFT (1024): 2033.507015924168
    SOR (100x100):   1887.3214307438175
    Monte Carlo : 1655.731504772598
    Sparse matmult (N=1000, nz=5000): 2590.355516411772
    LU (100x100): 6339.33044242166
    
    java.vendor: Private Build
    java.version: 11.0.15
    java..vm.vendor: Private Build
    java.vm.version: 11.0.15+10-Ubuntu-0ubuntu0.22.04.1
    os.arch: amd64
    os.name: Linux
    os.version: 5.15.0-41-generic
    

    Run jacobin (compiled with go 1.8): jacobin jnt.scimark2.commandline

    Jacobin VM v. 0.1.0, © 2021-2 by Andrew Binstock. All rights reserved. MPL 2.0 License.
    jnt.scimark2.commandline is not a recognized option. Ignored.
    

    Version information: openjdk version "11.0.15" 2022-04-19 x64 Xubuntu 22.04 LTS

  • Figure out why Github is failing a test that passes on the dev system and should pass on Github

    Figure out why Github is failing a test that passes on the dev system and should pass on Github

    The test is TestPrintOfCPpart2() in cpParser_test.go, which simply dumps the previously parsed constant pool (CP) entries to stderr.

    After adding some diagnostic info, got this, which is incorrect b/c it does not show the final two CP entries correctly, which are a dynamic and at UTF8 entry (from Github build and test #221)

        cpParser_test.go:867: dynamic CP entry did not appear in logging of CP contents:
            Number of CP entries parsed: 08
            CP entry: 00, type 00 (dummy entry)
            CP entry: 01, type 16 (method type)      description index: 4370
            CP entry: 02, type 18 (invokedynamic)    boostrap index: 4616, name and type: 4609
            CP entry: 03, type 01 (UTF-8 string)     Module
            CP entry: 04, type 19 (module name)      Module
            CP entry: 05, type 20 (package name)     Module
            CP entry: 06, type 00 (dummy entry)
            CP entry: 07, type 00 (dummy entry)
    

    The correct output should be:

    Number of CP entries parsed: 08
    CP entry: 00, type 00 (dummy entry)
    CP entry: 01, type 16 (method type)      description index: 4370
    CP entry: 02, type 18 (invokedynamic)    boostrap index: 4616, name and type: 4609
    CP entry: 03, type 01 (UTF-8 string)     Module
    CP entry: 04, type 19 (module name)      Module
    CP entry: 05, type 20 (package name)     Module
    CP entry: 06, type 17 (dynamic)          boostrap index: 4616, name and type: 4609
    CP entry: 07, type 01 (UTF-8 string)     Hello
    

    (Notice the difference in the last two entries.)

    After removing the Module and Package entries to see whether they were causing the problem, got the following output (from build and test #222):

            cpParser_test.go:867: dynamic CP entry did not appear in logging of CP contents:
            Number of CP entries parsed: 06
            CP entry: 00, type 00 (dummy entry)
            CP entry: 01, type 16 (method type)      description index: 4370
            CP entry: 02, type 18 (invokedynamic)    boostrap index: 4616, name and type: 4609
            CP entry: 03, type 01 (UTF-8 string)     Module
            CP entry: 04, type 00 (dummy entry)
            CP entry: 05, type 00 (dummy entry) 
    

    So, it's not the previous entries or their position that are causing the problem. Rather, it's the entries of themselves.

    Note: This issue is logged as JACOBIN-86 on the internal Jacobin task list (kept on YouTrack)

  • Local mutex makes no sense

    Local mutex makes no sense

    Local mutex does not make sense

    https://github.com/platypusguy/jacobin/blob/8818d325dae39b9a8a427359bd36ef330067e179/src/thread/jvmThread.go#L36

    shouldn't it be

    var addThreadToTableMutex = sync.Mutex{}
    func AddThreadToTable(t *ExecThread, tbl *list.List) int {
    	addThreadToTableMutex .Lock()
    
    	tbl.PushBack(t)
    	t.ID = tbl.Len() - 1
    	addThreadToTableMutex .Unlock()
    
    	return t.ID
    }
    
  • Is the plan to create a new JCL?

    Is the plan to create a new JCL?

    One of the key components of a Java SE implementation is the Class Library. Currently, I only know that OpenJDK has a complete implementation of the Class Library. It is a little coupled to the Hotspot VM, however, other JVMs, like OpenJ9 can use it.

    So my question is: Is one of the goals of this project reimplement the whole Java Class Library (like the java.lang.Object/java.util.HashMap, ...) or use the same as OpenJDK?

    There are some other implementations of some components that wouldn't be required to be implemented, like using the ECJ for the compiler and Kodda for a replacement of Javadoc.

    (The license of the JCL is GPL2, so it may play some role in the decision)

  • JACOBIN-166 - JMOD Support

    JACOBIN-166 - JMOD Support

    Adds support for JMOD files. Attempts to load java.base.jmod on startup, in order to replace the need for the JACOBIN_HOME setup. Test files are in testdata/jmod.

    One note: I didn't end up looking for the classlist in $JAVA_HOME/lib, because this made it less applicable to other modules in the future and also complicated testing a bit. I don't think it is necessary, as the classlist file should be in the module at all times anyway, but I can add that functionality in if you think it is necessary?

  • func Log and func shutdown contain a local mutex

    func Log and func shutdown contain a local mutex

    As written, I believe that simultaneous threads will never wait because the mutex variable is local to functions being called.

    Guessing from a Go newbie but I believe that you wanted to do something like this: https://notes.shichao.io/gopl/ch9/#mutual-exclusion-syncmutex and move the mutex definition to be global to the log package?

    Those are the only 2 cases (logger.go:Log & main.go:shutdown) that I saw where there are mutexes being used.

  • Uncomment lines from issue #1

    Uncomment lines from issue #1

    This PR is based on my creating a temporary repo and testing uncommenting out the lines referenced in issue #1. Either I have the magic touch [(-;] or Unka Andoo's activity last night somehow cleansed something (?).

  • Some jar files fail with

    Some jar files fail with "Invalid bytecode found: 20 at location 0 in method main()"

    Built a simple .jar file from a manifest and 3 small class files.

    ++ java -jar specrel.jar
    
    t_deltaAtRest: 10.0, x_lengthAtRest: 42.0
    v: 0.1 * c, Time(s): 10.0 --> 10.05037815259212
    	Length(m): 42.0 --> 41.78947235847804
    v: 0.2 * c, Time(s): 10.0 --> 10.206207261596576
    	Length(m): 42.0 --> 41.151427678757386
    v: 0.30000000000000004 * c, Time(s): 10.0 --> 10.482848367219182
    	Length(m): 42.0 --> 40.06544645951172
    v: 0.4 * c, Time(s): 10.0 --> 10.910894511799619
    	Length(m): 42.0 --> 38.49363583762906
    v: 0.5 * c, Time(s): 10.0 --> 11.547005383792516
    	Length(m): 42.0 --> 36.37306695894642
    v: 0.6 * c, Time(s): 10.0 --> 12.5
    	Length(m): 42.0 --> 33.6
    v: 0.7 * c, Time(s): 10.0 --> 14.002800840280099
    	Length(m): 42.0 --> 29.993999399879968
    v: 0.7999999999999999 * c, Time(s): 10.0 --> 16.666666666666664
    	Length(m): 42.0 --> 25.200000000000003
    v: 0.8999999999999999 * c, Time(s): 10.0 --> 22.94157338705617
    	Length(m): 42.0 --> 18.307375562870835
    
    
    ++ jacobin -jar specrel.jar
    
    Invalid bytecode found: 20 at location 0 in method main() of class specrel/CommandLine
    
    Error: could not find or load class specrel/Lorentz.
    Error: could not find or load class specrel/Formulae.
    

    See README.txt in the attached ZIP file for tree layout (small), bash scripts, and Java source files.

    tinyjar.zip

Highly extensible, customizable application launcher and window switcher written in less than 300 lines of Golang and fyne
Highly extensible, customizable application launcher and window switcher written in less than 300 lines of Golang and fyne

golauncher A go application launcher A simple, highly extensible, customizable application launcher and window switcher written in less than 300 lines

Aug 21, 2022
XSD (XML Schema Definition) parser and Go/C/Java/Rust/TypeScript code generator

xgen Introduction xgen is a library written in pure Go providing a set of functions that allow you to parse XSD (XML schema definition) files. This li

Jan 1, 2023
Build reply markup keyboards easier than ever.

gotgbot keyboard Build reply markup keyboards easier than ever.

Feb 24, 2022
My Go solution that's faster than 95%

Palindrome-Partitioning My Go solution that's faster than 95% "Given a string s, partition s such that every substring of the partition is a palindrom

Nov 15, 2021
Chaosblade executor for chaos experiments on Java applications
Chaosblade executor for chaos experiments on Java applications

Chaosblade-exec-jvm: Chaosblade executor for chaos experiments on Java applications Introduction The project is a chaosblade executor based on jvm-san

Dec 16, 2022
Zinc Search engine. A lightweight alternative to elasticsearch that requires minimal resources, written in Go.
Zinc Search engine. A lightweight alternative to elasticsearch that requires minimal resources, written in Go.

Zinc Search Engine Zinc is a search engine that does full text indexing. It is a lightweight alternative to Elasticsearch and runs using a fraction of

Jan 1, 2023
Optimistic rollup tech, minimal and generic.

Opti Optimistic rollup tech, minimal and generic. VERY experimental, just exploratory code, question is: 1:1 EVM rollup with interactive fraud proof p

Aug 30, 2022
Minimal example app of hexagonal architecture in go

Hexagonal Architecture Minimal example of hexagonal architecture (ports & adapters) in go. Resources T

Nov 5, 2021
gosignal is expected to be used in minimal window manager configurations

gosignal is expected to be used in minimal window manager configurations. It provides a simple battery monitor , which notifies of battery events. It has a config file where you can configure the notification messages given

Mar 21, 2022
Gec is a minimal stack-based programming language

Gec is a minimal stack-based programming language

Sep 18, 2022
A simple Cron library for go that can execute closures or functions at varying intervals, from once a second to once a year on a specific date and time. Primarily for web applications and long running daemons.

Cron.go This is a simple library to handle scheduled tasks. Tasks can be run in a minimum delay of once a second--for which Cron isn't actually design

Dec 17, 2022
Workaround for running ubuntu:21.10, fedora:35, and other glibc >= 2.34 distros on Docker <= 20.10.9

clone3-workaround: Workaround for running ubuntu:21.10, fedora:35, and other glibc >= 2.34 distros on Docker <= 20.10.9 Old container engines such as

Dec 1, 2022
Quickly clone an entire org/users repositories into one directory - Supports GitHub, GitLab, Bitbucket, and more
Quickly clone an entire org/users repositories into one directory - Supports GitHub, GitLab, Bitbucket, and more

ghorg ghorg allows you to quickly clone all of an orgs, or users repos into a single directory. This can be useful in many situations including Search

Jan 1, 2023
Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.
  Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.

gore Yet another Go REPL that works nicely. Featured with line editing, code completion, and more. (Screencast taken with cho45/KeyCast) Usage gore Af

Jan 7, 2023
Heat, heat and more heat!
Heat, heat and more heat!

Load Operator The intention of this project is to escape from the bad weather during the winter season. ;) Instead of getting wet and cold, it is used

Nov 15, 2021
A patcher for the MS-DOS version of Fallout 1 including Crafty's sFall1 patches and maybe more

A patcher for the MS-DOS version of Fallout 1 including Crafty's sFall1 patches and maybe more

Oct 13, 2022
The VM for running Back

Backvm The VM for running Back Back is a Concurrent Forth implementation, have fun Building the only dependency for backvm is the Go compiler Backvm d

Dec 11, 2021
Search running process for a given dll/function. Exposes a bufio.Scanner-like interface for walking a process' PEB

Search running process for a given dll/function. Exposes a bufio.Scanner-like interface for walking a process' PEB

Apr 21, 2022
Unik is a Go module for running Go programs as unikernels, without an underlying operating system

Unik is a Go module for running Go programs as unikernels, without an underlying operating system. The included demo is a functional Gio GUI prog

Oct 21, 2022