4 ms·
There has been multiple C compilers targetting the JVM, however they've all also had bad performance penalties since the JVM has no notion of references and poi
by whizzter 3y ago
There has been multiple C compilers targetting the JVM, however they've all also had bad performance penalties since the JVM has no notion of references and pointers so it becomes "emulated", best case you write one that works on ByteBuffer objects (Like early Asm.JS before WASM used a WebGL TypedArray objects before they became part of JavaScript proper) but once you go that route it becomes frustrating to interface with the rest of the Java ecosystem (and you kinda loose the entire point of a JVM targeting C compiler).
Even Sun/Oracle recognized the mismatch and that's why GraalVM is a thing (and why Graal isn't entirely meshable with classic Java runtimes even if I hope they have a merge-strategy for the long-term).
- warrenm 3y agoJava understands "references" and "pointers" (or, at least did in the 1.6 (and before) era...does it not any more?)
- Someone 3y agoJava doesn’t have pointers in the C sense. Code such as while(*dst++=*src++); or char buf[100]; char *p = buf+13; p[-3] = p[1]; doesn’t map well to the JVM. As others said, you’d have to (almost) emulate memory in a byte array or byte buffer to fully support C.
- Thiez 3y agoNot like C. They are not comparable. You get a reference to something you allocate on the heap, and you can have primitives on the stack. But you cannot take a reference to a primitive, or a reference to another reference, or a reference to the second element of an array. To run C on the JVM you are really swimming uphill.
- kaba0 3y agoYou see &variable in a function body, you allocate a stackframe for that in the heap abstraction and return that’s address.
- Thiez 3y agoAnd now for a reference to a field in a struct living on the heap? Of course you can get C to run on the JVM (any CPU emulator written in Java proves that) but due to JVM limitations you cannot do so efficiently. Which is why it the JVM is not an attractive target for the 'traditional' languages.
- kaba0 3y agoThat struct on the heap is just consecutive bytes in an array, so you just return an integer.
- Thiez 3y agowarrenm was asking whether Java's (and implicitly: the JVMs) concept of references could be used. I'm glad that you agree with me that they cannot. Representing the memory of a compiled C program with a giant byte array would of course work, but also defeat the purpose of running on the JVM in the first place. You lose all the advantages that running on the JVM might have given you, and are slower than a natively compiled program.
- 4RealFreedom 3y agoI think the point is that you are unable to address memory in the same way as C because the underlying technologies are different.
- w7 3y agoIt has references, but from what I understand they don't entirely conceptually match in use, implementation, and semantics to C++ references.
- kaba0 3y agoIt has pointers aliased as references. They are pointers for all practical purposes. NullPointerException is named as such for this very reason - pointers were considered scary back then, hence the marketing term.
- w7 3y agoYes, implementation wise underneath in most cases they're likely some structs/pointers/whatever, but the point was that interaction with them from the perspective of an application running on the JVM is not the same as what the JVM sees itself, nor are the same exact operations available-- you'd have to create abstractions or use implementation specific jdk.internal.misc.* calls, and at that point why are you using the JVM.
- KMag 3y agoC++ and Java reference semantics are very different. Java, like Python, has a model of "references passed by value". void caller() { T a = new T(0); T b = new T(1); callee(a, b); } void callee(T a, T b) { a = b; } In Java, a and b are references, but from caller's perspective, callee is a no-op. On the other hand, using C++'s reference semantics, (and replacing T with T&) callee would modify the a object, not just locally change the reference.
- kaba0 3y agoI don’t see its relevance, that’s up to the compiler to “solve”, adhering to reference’s semantics. It is just pointers/transformations either way in machine code, which can be trivially emulated in any language/platform that has an array of bytes available.
- KMag 3y agoYes, the language runtime version of the "Turing tarpit". Any Turing-complete system can emulate any other. However, in this case, you're bounds-checking absolutely every memory operation, whereas with native Java field access, the class verifier proves the field access is legal just once at class load time.
- kaba0 3y agoThe JIT compiler can elide most of those just as well at runtime
- KMag 3y agoThe JVM can elide most of the Java bounds checks because it has much more static information from Java class files than is available from C code. Once you're emulating a memory-unsafe language, you lose most of those static semantic guarantees you get from valid Java code. In the general case, in a memory unsafe language, statically removing bounds checks is equivalent to solving the halting problem. One could definitely add some extra load-time static analysis to the JVM, similar to what the NaCL / PNaCL did at binary load time to greatly increase the opportunities for JVM bounds check removal. However, this would need some extensions to the class file format and/or some new class file annotations to expose some more static information than the JVM has for vanilla Java class files. In addition, there are also plenty of ways one could optimize away some bounds checks based on undefined behavior, which would result in a standards-conforming C implementation, yet break tons of C code in the wild. (There at least used to be a C to Go transpiler that implemented C unions this way.) For instance, it's UB to write to one field of a union and then read another field, so it'd be legal for a compiler to implement a union as a struct. However, there's plenty of code in the wild (such as many nanboxing/nunboxing implementations) that rely on union fields occupying the same physical addresses.