{"id":16988534,"url":"https://github.com/chaoyangnz/gava","last_synced_at":"2026-03-16T20:04:44.050Z","repository":{"id":145177023,"uuid":"93152316","full_name":"chaoyangnz/gava","owner":"chaoyangnz","description":"🚀 A sandboxed VM any Java developer can afford","archived":false,"fork":false,"pushed_at":"2023-08-07T08:43:46.000Z","size":66411,"stargazers_count":173,"open_issues_count":1,"forks_count":20,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-05T22:41:23.784Z","etag":null,"topics":["bytecode","go","golang","interpreter","java","vm"],"latest_commit_sha":null,"homepage":"https://gava.netlify.app","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chaoyangnz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-02T09:53:54.000Z","updated_at":"2025-02-26T04:00:52.000Z","dependencies_parsed_at":"2024-10-27T12:58:33.235Z","dependency_job_id":null,"html_url":"https://github.com/chaoyangnz/gava","commit_stats":{"total_commits":199,"total_committers":8,"mean_commits":24.875,"dds":"0.23115577889447236","last_synced_commit":"d5cebd8694336384fd4bf719472461127096a96b"},"previous_names":["chaoyangnz/gava"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chaoyangnz/gava","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaoyangnz%2Fgava","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaoyangnz%2Fgava/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaoyangnz%2Fgava/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaoyangnz%2Fgava/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chaoyangnz","download_url":"https://codeload.github.com/chaoyangnz/gava/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaoyangnz%2Fgava/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260708653,"owners_count":23050067,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bytecode","go","golang","interpreter","java","vm"],"created_at":"2024-10-14T03:04:15.974Z","updated_at":"2026-03-16T20:04:44.010Z","avatar_url":"https://github.com/chaoyangnz.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](https://github.com/chaoyangnz/gava/workflows/build/badge.svg?branch=master)\n![](https://img.shields.io/github/go-mod/go-version/chaoyangnz/gava?style=flat-square\u0026branch=master)\n\n# Gava\n\n\u003cimg src=\"gava.svg\" width=\"60\" height=\"60\"/\u003e\n\n**NOTE**: (previously named `Javo/Jago`)\n\n\u003e This project is not supposed to extend the features, more focus will be moved to its sister project [zava](https://github.com/chaoyangnz/zava) - a rewrite in Zig\n\nA simplified Java virtual machine written in Go language. One aim is to learn JVM specification in depth and try to understand the behind-the-scene behaviour when a Java program runs. This VM can be used for the educational purpose, for example, for a course about how to design a runtime for a language with the complete specification.\n\nI only refer to \"Java Virtual Machine Specification\" and then look into how we should design one.\nSome production-level features are intentionally ignored and it is supposed to make it as simplified as possible so as to\ndemonstrate the general idea. For the educational purpose, it is more than enough.\n\nIf you have no time to read OpenJDK source code or always guess the JVM behaviour when you need to tune your program, then your right here to be the lord of your universe.\n\nA overview presentation can be found: https://drive.google.com/file/d/1gESJTwm_tJL8pA7WBxJfhz4iUW7KwihP/view?usp=sharing\n\n![](https://i.imgur.com/IWWtSYY.gif)\n\nAny thought is welcome and I am happy to be wrong.\n\n# Roadmap\n\n- [x] Java class file reader\n- [x] Interpreter engine\n- [x] Class loader delegation\n- [x] multi-threading support\n- [x] monitor, `sleep`, `wait`, `notify` support\n- [x] JDK native methods\n- [ ] GC\n- [ ] JIT\n\n# How to run\n\n## build and install\n\n```bash\n❯ cd ~/gava\n❯ ./build.sh\n```\n\nBy default, gava will be installed to `/usr/local/gava`\n```text\n/usr/local/gava\n├── bin\n│   └── gava\n├── jdk\n│   └── classes\n│       ├── META-INF\n│       ├── apple\n│       ├── com\n│       ├── java\n│       ├── javax\n│       ├── jdk\n│       ├── org\n│       └── sun\n└── log\n    ├── classloader.log\n    ├── io.log\n    ├── misc.log\n    ├── thread-bootstrap.log\n    ├── thread-main.log\n    └── threads.log\n```\n\n## gava command\n```bash\n❯ gava -h\nNAME:\n   Gava - A simplified Java Virtual Machine for the educational purpose\n\nUSAGE:\n   gava [-options] class [args...]\n\nVERSION:\n   1.0.0\n\nDESCRIPTION:\n   A Java* Virtual Machine demonstrating the basic features of execution engine, class loading, type/value system, exception handling, native methods etc.\n\nAUTHOR:\n   Chao Yang \u003cchao@yang.so\u003e\n\nCOMMANDS:\n     help, h  Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --classpath value, --cp value  application classpath separated by colon\n   --noLogo, --nl                 don't show logo\n   --debug, -d                    debug mode\n   --trace, -t                    trace mode\n   --log:thread value             log level of instruction execution in a thread context, options: info, debug, trace\n   --log:classloader value        log level of class loading, options: info, debug, trace\n   --profile, -p                  profile gava\n   --help, -h                     show help\n   --version, -v                  print the version\n```\n\n### Run a calendar program\n\n```bash\n❯ gava -nl -cp . Calendar 8 2018\n```\n![](https://i.imgur.com/teTi3Ph.gif)\n\n### Run a pyramid program\n\n```bash\n❯ gava -nl -cp . Pyramid\n```\n![](https://i.imgur.com/lJsHits.gif)\n\n### run a program traversing a tree in the level order\n\n```bash\n❯ gava -nl -cp . TreeLevelOrderTraverse\n```\n![](https://i.imgur.com/1Oyq7Ep.gif)\n\n### Run a program into exception\n\n```bash\n❯ gava -nl . test/test_athrow\n```\n![](https://i.imgur.com/lDxICzN.gif)\n\n### More examples to demonstrate features\n\n- Print system properties\n```bash\ngava -d test.test_system_properties\n```\n\n- Multi-threading\n```bash\ngava -d test.test_thread\n```\n\n```bash\ngava -d Multithread\n```\n\n- Thread sleep or `wait` / `interrupt`\n```bash\ngava -d SleepInterrupt\n```\n\n```bash\ngava -d WaitInterrupt\n```\n\n- Java monitor lock with `synchronized`\n```bash\ngava -d Counter\n```\n\n- Java wait() and `notify()`, `notifyAll()`\n```bash\ngava -d ProducerConsumer\n```\n\n## trace the execution\n\n### log/thread-[name].log \nThis log file records the each instruction execution and method call hierarchy within a thread context. Set the log level to info to view call hierarchy more clearly.\n\nThe blue diamond symbol 🔹 means pure Java methods while the yellow one 🔸 means native methods which is implemented within Gava internally.\n\nThe fire symbol 🔥 means exception throwing (thrown by `athrow` bytecode, rethrown if uncaught or thrown by VM internally), while the blue water symbol 💧 means an exception is caught by a method.\n\n- TRACE: log all low level bytecode instructions, method call and exception thrown/caught\n- DEBUG: only method call and exception thrown/caught\n- INFO: only exception thrown/caught info\n\n![](https://i.imgur.com/q0033Kl.gif)\n\n\n### log/classloader.log \nThis log file records the class loading process, including what triggers a class loading and when its class initialization method \\\u003cclinit\\\u003e is invoked.\nThe trigger reason can be viewed after a class name.\n\n![](https://i.imgur.com/eN8foXd.gif)\n\n### log/threads.log\n\nThis log file records thread creation/exit information and object monitor enter/exit, thread sleep(), wait(), notify() etc.\n\n### log/io.log\nThis log file records I/O details around system interactions.\n\n![](https://i.imgur.com/1eQe95o.gif)\n\n### log/misc.log\nOther trivial logs\n\n![](https://i.imgur.com/2kgfhhb.gif)\n\n# Profiling\n\nhttps://flaviocopes.com/golang-profiling/\n\n- install Graphviz\n- run gava with `-p` option\n- `go tool pprof --pdf /usr/local/bin/gava /var/../cpu.pprof \u003e cpu.pdf`\n\n# Documentation\n\nReally sorry, I have no time to write documentation but it is in my plan.\nThe Ebook about how it works internally is in progress: https://www.gitbook.com/book/chaoyangnz/go-my-jvm\n\n# Testing\n\nI am really keen to get missing tests done if I have time. Another reason I didn't enjoy writing tests in Go is that I cannot find an awesome unit test library like Jest. For some libraries I looked into, it requires me to change my code just for testing. I don't like the idea about breaking the encapsulation just for testing. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaoyangnz%2Fgava","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchaoyangnz%2Fgava","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaoyangnz%2Fgava/lists"}