{"id":15069499,"url":"https://github.com/jakewins/jaa","last_synced_at":"2025-04-10T16:52:26.512Z","repository":{"id":57725487,"uuid":"115563346","full_name":"jakewins/jaa","owner":"jakewins","description":"Actionable memory analysis for JVM languages","archived":false,"fork":false,"pushed_at":"2017-12-29T22:45:12.000Z","size":102,"stargazers_count":17,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T14:44:35.287Z","etag":null,"topics":["java","jvm","jvm-performance","kotlin","openjdk","scala"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jakewins.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}},"created_at":"2017-12-27T22:45:03.000Z","updated_at":"2024-01-13T23:57:42.000Z","dependencies_parsed_at":"2022-09-11T20:30:48.446Z","dependency_job_id":null,"html_url":"https://github.com/jakewins/jaa","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakewins%2Fjaa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakewins%2Fjaa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakewins%2Fjaa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakewins%2Fjaa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jakewins","download_url":"https://codeload.github.com/jakewins/jaa/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248256266,"owners_count":21073493,"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":["java","jvm","jvm-performance","kotlin","openjdk","scala"],"created_at":"2024-09-25T01:42:53.550Z","updated_at":"2025-04-10T16:52:26.490Z","avatar_url":"https://github.com/jakewins.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/jakewins/jaa.svg?branch=master)](https://travis-ci.org/jakewins/jaa)\n\n# JVM Allocation Analyzer, JAA\n\nJVM allocation analysis that filters out allocations HotSpot optimizes out.\n\nThis gives you allocation reports that are actionable, meaning if you address the top allocations in the report, \nyou'll make a good dent in actual production heap usage.\n\n## Minimum viable snippet\n\nAdd dependency:\n\n    \u003cdependency\u003e\n      \u003cgroupId\u003ecom.jakewins\u003c/groupId\u003e\n      \u003cartifactId\u003ejaa\u003c/artifactId\u003e\n      \u003cversion\u003e1.1.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \nWrite analysis case:\n\n    public class SimpleExample {\n    \n        public static void main(String ... argv) throws IOException {\n            new Jaa(new Options.Builder()\n                    .include(SimpleExample.class)\n                    .withReportFolder(Paths.get(\"./target/allocation-reports\"))\n                    .build())\n                    .run();\n        }\n    \n        @AllocationAnalysis\n        public void simple() {\n            System.out.println(\"Hello, world!\");\n        }\n    }\n\nSee [examples](src/main/java/jaa/examples) for more running code.\n\n## Rationale\n\nThere are many ways to analyze allocations on the JVM - object counting, TLAB acquisition tracking, etc. \nIf you want an exact account of what was allocated and where, instrumenting bytecode is the way to go.\n\nHowever, instrumenting byte code to track each allocated object makes it impossible for the JVM to perform standard optimizations.\nThe reports become filled with allocations that the JVM would optimize into stack allocations or remove altogether under normal operation.\n\nThe end result being that the reports are not actionable - if you fix the worst allocation points from an instrumentation-based report,\nyou're likely to make no difference to your programs performance, since you're just manually doing HotSpots job.\n\nJAA analyses memory in three steps:\n\n1. Execute the test without instrumentation with `-XX:+PrintEliminateAllocations`. Use the output from this to build an index of allocations the JVM removes already.\n2. Execute the test with instrumentation\n3. Filter the report from (2) with the data from (1)\n\nThis gives you a report of allocation points the JVM does not move to the stack or remove, substantially improving the usefulness of the analysis.\n\n## Limitations\n\n- Java 8 only, for now\n- OS X users need to manually acquire a `fastdebug` build of OpenJDK (consider +1 [here](https://github.com/AdoptOpenJDK/openjdk-build/issues/146) to solve this)\n- Ambiguity in OpenJDK debug output could lead to reports excluding the wrong thing. OpenJDK only outputs the class names, not the fully qualified names, so two allocation points allocating the exact same object could end up tricking JAA to eliminate the wrong allocation. \n\n## License\n\nGPLv3\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakewins%2Fjaa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjakewins%2Fjaa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakewins%2Fjaa/lists"}