19 ms·
Show HN: I spent my vacation writing a modern JVM assembler
- self_awareness 4y agoGood method of helping to manually obfuscate some calls, so that reverse engineering can be harder.
- noone_youknow 4y agoI had a lot of fun doing this, and along the way I learned a lot about writing Gradle and IntelliJ plugins, and I hope others might find this fun too :)
- drdrey 4y agoThis looks great! I love that you kept the shape of Java classes and method definitions but with the low level signatures. Over a decade ago, I used to maintain Jasmin and some other class file tooling :)
- noone_youknow 4y agoThanks :) Small world, I currently help maintain Jasmin (via involvement in Code Shelter).
- recursivedoubts 4y agoamazing! I will definitely discuss this in my compilers class, which targets JVM bytecode as a back end!
- noone_youknow 4y agoAwesome, thanks! Would love to hear if it turns out to be interesting (or maybe even useful!)
- eternalban 4y ago... checkcast java/lang/String areturn Looks like a typo.
- mbfg 4y agoareturn is return an object, as opposed to ireturn (return a primitive int, dreturn, lreturn, etc, etc.)
- newobj 4y agono, areturn is a jvm opcode.
- eternalban 4y agoah. TIL.
- cbm-vic-20 4y ago"Let's just get this out of the way, shall we? {code here} " Thanks for doing that; I can't stand it when I go to a site for something new and can't find what it actually looks like without digging around.
- noone_youknow 4y agoI couldn't agree more, I'm a big fan of "show me the code" myself.
- deleted 4y ago[deleted]
- tornadofart 4y agoImpressive
- noone_youknow 4y agoThanks :)
- jpgvm 4y agoThis is awesome. I have been toying with writing my own little JVM language (for education purposes) and this could go a long way to making that a bunch easier. Thanks for sharing!
- noone_youknow 4y agoAwesome! I started this for educational purposes too, but if it turns out to be useful then I'll be very happy! Hope it turns out that way (and let me know if there's anything else you need to make it useful! :) )
- kjeetgill 4y agoIf you haven't heard of it already check out Truffle/graalvm
- jpgvm 4y agoI have but Truffle was a bit further than I wanted to go for now. If I wanted to build a production ready language it would likely be my first choice though.
- deleted 4y ago[deleted]
- hashmash 4y agoFor the code generation phase, it might be easier to bypass emitting a text-based assembly format and just use the ASM library directly. If you want something easier, I wrote a code generation library specifically for that purpose: https://github.com/cojen/Maker https://github.com/cojen/Maker It also includes an example "Mini-C" language compiler.
- j_ham3 4y agoSomething else that could make your code generation for your JVM language easier: ProGuardCORE (https://github.com/Guardsquare/proguard-core https://github.com/Guardsquare/proguard-core). It can be used to read, generate and analyse Java bytecode. Some examples for code generation: ProGuard where the project originated (https://github.com/Guardsquare/proguard https://github.com/Guardsquare/proguard), Brainf*ck compiler (https://github.com/mrjameshamilton/bf https://github.com/mrjameshamilton/bf), Lox compiler (https://github.com/mrjameshamilton/klox https://github.com/mrjameshamilton/klox) Disclaimer: I work at Guardsquare on ProGuardCORE so may be biased :)
- playing_colours 4y agoCan anyone recommend a good source (book, articles) to learn Java Bytecode?
- topbanana 4y agohttps://docs.oracle.com/javase/specs/jvms/se17/html/index.html https://docs.oracle.com/javase/specs/jvms/se17/html/index.ht... and for .Net CIL https://www.ecma-international.org/publications-and-standards/standards/ecma-335/ https://www.ecma-international.org/publications-and-standard...
- rzzzt 4y agoThe JVM spec is a bit dry but readable: https://docs.oracle.com/javase/specs/jvms/se17/html/index.html https://docs.oracle.com/javase/specs/jvms/se17/html/index.ht...
- noone_youknow 4y agoThere's a "cookbook" document in the repo, but it's not very comprehensive - I'd be more than happy to take PRs :) https://github.com/roscopeco/jasm/blob/develop/docs/cookbook.md https://github.com/roscopeco/jasm/blob/develop/docs/cookbook...
- jfengel 4y agoThere's a very old but still pretty effective book called Programming for the Java Virtual Machine. Byte code is remarkably stable. (Disclaimer: author)
- dvt 4y agoVery cool! Reminds me of a little toy (and very unfinished) project I worked on almost a decade ago (jeez, can't believe it's been that long): https://github.com/dvx/jssembly https://github.com/dvx/jssembly Even our syntax is somewhat similar, though you're using plugins for cleaner code which is an awesome idea.
- noone_youknow 4y agoAwesome, I'm gonna have to take a good look at your project, it's very interesting! Thanks :)
- tstack 4y agoI used to use jasmin to generate invalid code to test an old JVM. I assume this has the same relaxed attitude that will let you generate invalid code?
- noone_youknow 4y agoIt sure will, as an assembler it only does the bare minimum of validation, so you should totally be able to generate "dodgy" code and see if it works on older JVMs :)
- pdpi 4y agoI implemented a .class disassembler a while back by literally reading the spec. It's surprisingly accessible.
- noone_youknow 4y agoIt really is. We've Sun to thank for that I think.
- deleted 4y ago[deleted]
- weaksauce 4y agoYeah we had to create a java compiler and java interpreter in the compiler class I took(of course it was just a small subset of the runtime) pretty fun project for school but tedious.
- jbaiter 4y agoYeah, I had to write a small bytecode patcher from scratch the other day and was amazed at the quality of the writing in the spec. Took me all but 2h to implement what I wanted, with no real prior knowledge of JVM bytecodes and class file structure.
- Strs2FillMyDrms 4y agoMy question (if I may), When people say the bytecode is "platform independent" I ask, exactly what platform is it being freed from? The compiler? The "cloud"? And this goes back to my lack of understanding of what "publishing" a package means to Oracle and the ecosystem in general. If I publish something on Maven, my guess is that it is transformed into bytecode directly, so that when I pull my package from a diff device the code can run. In this case if the entire "internet" collapses then the only way to run my code would be a flashdrive with the .java file run via a compiler... unless there is a machine that has the JVM installed WITHOUT the compiler... THEN the bytecode is useful... Am I correct?
- wrs 4y agoIt is independent of the processor architecture, and to a large extent the operating system. (As opposed to an ordinary binary executable, which depends on both.) The compiler turns Java source into bytecode. The JVM runs the bytecode. The JVM doesn’t need the compiler to run.
- Strs2FillMyDrms 4y agoThanks for your response. What I get from this is that the processor arch. Is dictated by the compiler at compile time, and by writing to bytecode directly we are skipping this. I thought the proc. arch. was established by the manufacturer and was unavoidably implemented by the jni at runtime... unless there is an interface on top of the jn-interface to deal with the proc. But it seems absurd... why do this at compile time?
- wrs 4y agoThe JVM is a native-code application (i.e., running on the processor directly) that executes the bytecode by interpreting it (starts fast, but runs slowly) and/or converting it into native code and running that code on the processor directly (delayed by the conversion step, but then runs fast). The latter step, translating bytecode to native code, is known as the just-in-time (JIT) compiler. So somewhat confusingly, Java typically involves two compilers: one from source code to bytecode, the other from bytecode to native code. By nature, the first is processor-independent, the second is processor-dependent. The second happens at runtime on the target machine — thus, “write once, run anywhere”.
- oh_sigh 4y agoI enjoyed reading about doing some things with the jvm which are not possible through the java language - can anyone recommend a page that goes further into that concept?
- saagarjha 4y agohttps://kotlinlang.org https://kotlinlang.org ;)
- mindcrime 4y agoI'm not sure how many of them expose features that are literally not possible in Java per-se, but there are approximately a gazillion different languages out there that emit Java bytecode. Reading up on some of them might be enlightening. https://en.wikipedia.org/wiki/List_of_JVM_languages https://en.wikipedia.org/wiki/List_of_JVM_languages
- donsupreme 4y agoBravo! you and I have very different way to decompress during a vacation
- noone_youknow 4y agoHaha yes, I'll admit there are probably better ways to decompress :D
- mdaniel 4y agoI dunno about OP, but it's not that I hate programming, the stress comes from dealing with the people and sometimes working on draining problems. The more frustrated I get at work, the higher my S.O. reputation gets because I find comfort in helping to answer impactful questions
- ElijahLynn 4y agoThese are the type of posts that make some of us noobs feel like imposters, lol. (been coding webstack-ish for 10 years, fwiw, can't even begin to write an assembler though :shrug:) Good on you though, we need inspiration too! And you definitely should feel great about pulling that off! I am imaging it must have been some really fantastic "flow" time! How did you feel while writing it? Did you have family or friend distractions? Did you feel super focused? What is that story? What are some of your focus patterns that you have identified? What gets you motivated when you feel stuck?
- deleted 4y ago[deleted]
- brailsafe 4y agoIf you had the skill and wherewithal to do something like this, would you want to spend vacation doing it? I think it's neat, but I'd probably want to get the hell away from my screen
- chrisseaton 4y ago> can't even begin to write an assembler An assembler is a 1-1 mapping. If you can read some text, and you can write some bytes, then you can write an assembler. Everything in between is just a case of reading the manual! It's just some ifs - if the user's written this instruction name, then emit these bytes. I work on compilers and I'm awe of people who work on web apps because they genuinely seem far more complicated than what I do.
- boardwaalk 4y agoI mean, there is usually a pass to resolve labels, right? So it's not quite that simple. But not far from it.
- saagarjha 4y agoThat depends on how fancy you want to be, you can definitely implement an assembler with relative branches and no labels.
- FastEatSlow 4y agoBrilliant, much better than having to use heavy and clunky tools like recaf or jbytemod, or one-off java projects with ow2 ASM to create custom classes.
- userbinator 4y agoThat syntax seems to be implying that the next step is to integrate this into the compiler, so you can write inline Asm in Java.
- noone_youknow 4y agoThat's either the best or the worst idea I've ever heard. I can't decide which... :D
- mbfg 4y agoLooks like a fun project. One thing i'd be interested in, is if it's slower than using javac, given that the JIT can optimize common idioms that the compiler spits out. For instance, for some JITs, in the past anyway, This code int myNumber = getANumber(); String s = "" + myNumber; was faster to run than int myNumber = getANumber(); String s= String.valueOf(myNumber); even though the bytecode for the second bit of code is a proper subset of the first. (Meaning the first section had all the byte code of the second, plus some extra stuff.) And yet the first ran faster than the second. So unless you've got some spectacularly tricky algorithm that you can naturally express in java, and can in jasm, i'm betting the javac output will be as fast or faster. Again tho, i'm not criticizing the author for doing this project at all. Kudos!
- pvg 4y agoThe purpose of this thing isn't really performance but fun and exploration, if I'm reading the author's comments right. For examples like yours though, between the static analysis done by the compiler, whatever the JIT does and intrinsics, you can't readily predict what's going to run faster by looking at the Java code or the bytecode. These days, a much broader range of things that are equivalent-looking end up performing the same once the JIT gets involved, including stuff that seems to be naively doing allocations in inner loops. There's a whole genre of SO questions and answers that boil down to throwing a micro-example like yours into JMH and finding out they have identical performance profiles.
- noone_youknow 4y agoOh yeah, totally. As another reply mentions, this isn't about performance - by this point Javac is most likely doing the best thing possible (especially given the knowledge of hotspot and intrinsics that are built in to it). I kind of hint at this in the readme :) That said, this doesn't _have_ to be any slower than Javac - in fact I recommend looking at the disassembly of classes compiled with Javac to see how things work under the hood :)
- mrslave 4y agoWhy not Jasmin? Congrats on publishing your application. If this was something more than self-education please sell the benefits over Jasmin in your README? Looking forward to having a play with it.
- noone_youknow 4y agoThat's a great suggestion, I'll get the README updated with that. Thanks!
- deleted 4y ago[deleted]
- nnoitra 4y ago"With my recent scaling-back of the rosco_m68k project that’s been getting all my free time for the past couple of years, I needed a fun project to do during my time off, and I ideally wanted to take a break from Motorola 68k assembly and electronics and do something different." All of your free time is consumed in programming? Isn't it a bit absurd to have your entire life revolve around programming?
- jdlshore 4y agoNot nearly as absurd as thinking it’s okay to criticize strangers’ hobbies.
- gavinray 4y agoI don't think so, if that's your passion and you have no other hobbies. Why is programming for fun worse than birdwatching or building model trains? My joke is always: "Wait, you guys are getting paid for this?"
- nnoitra 4y agoYeah but birdwatching at least implies that the activity is varied. What if someone was laying bricks for 9 hours and then came home ate dinner and then laid bricks for 3 more hours and did this for years and then took a vacation and laid bricks during the vacation as well? The line is murky between passionate, dedicated, obsessed and insane. I mean, do we understand that we get a single shot at life. This year we'll be as young as we'll ever be. Why do we behave as if though we have endless days that we can just toss away and be done with. Programming full-time and then also during free time and vacations is simply put not healthy no matter how much Elon Musk and the west glamourise it. It simply leaves no time whatsoever for taking care of health, spending time with family, travelling, photography, reading novels, meeting romantic partners etc.
- noone_youknow 4y ago> What if someone was laying bricks for 9 hours and then came home ate dinner and then laid bricks for 3 more hours and did this for years and then took a vacation and laid bricks during the vacation as well? Well, then I would surmise that they must really enjoy laying bricks. And if that's the case, then more power to them :) > I mean, do we understand that we get a single shot at life. I'm pretty sure we do. And some of us are lucky enough that we get to choose how we spend it :)
- rurban 4y agokotlin is modern now? I would not dare to use jasm in my hypothetical new language targeting the JVM. I'd rather write this anew in C++ or C.
- j_ham3 4y agoNice project! At Guardsquare, we have a similar project: https://github.com/Guardsquare/proguard-assembler https://github.com/Guardsquare/proguard-assembler One of the things we use it for is testing: we can craft specific bytecode sequences that we want to test; for example, it's useful to test cases we've seen in the wild (e.g. obfuscated code) or to create a test that doesn't rely on a specific compiler/version. An example of using the assembler from a ProGuard unit test https://github.com/Guardsquare/proguard/blob/master/base/src/test/kotlin/proguard/util/ProguardAssemblerTest.kt https://github.com/Guardsquare/proguard/blob/master/base/src...
- noone_youknow 4y agoAwesome, that's a very interesting project! Thanks for the link :)
- brabel 4y agoGroovy version of this but based off Jasmine: https://github.com/renatoathaydes/Grasmin https://github.com/renatoathaydes/Grasmin
- H4sh3 4y agopublic static main([java/lang/String)V { is this open square brackets a typo?
- noone_youknow 4y agoNope, that’s the syntax for a one-dimensional array of strings. I wanted to keep the syntax as close to JVM internal type names as possible.