Only if talking about microcontrolers with few hundred KB, where even C is a challenge.
There are Java and Oberon implementations for single digit MB, like Cortex-M4.
So? Just because you can use a language on a given system doesn't mean that you should use it in any serious context.
A GC typically makes memory usage and execution latency non-deterministic, or at the least very hard to analyze. If your washing machine software OOMs whenever the GC didn't run between two button pushes, you'll have a great Heisenbug.
Here is just one of them.
http://www.militaryaerospace.com/articles/2006/10/lockheed-m...
"PERC Ultra offered Lockheed Martin the responsiveness it needed to meet its most demanding timing requirements. In addition to real-time threading and deterministic garbage collection, PERC Ultra provided the instrumentation and VM management tools necessary to support the mission-critical real-time requirements of the Aegis Weapon System."
"The Lockheed Martin-developed Aegis Weapon System is the sea-based element of the U.S. Ballistic Missile Defense System. The Aegis Weapon System is a radar and missile system integrated with its own command and control system, capable of simultaneous operation defending against advanced air, surface, and subsurface threats."
Is that serious enough for you?
You could say same about malloc and free. Not deterministic at all either. Memory fragmentation is a huge issue as well, and can bring down the whole system.
Typical GC (not all flavors) has a huge advantage on microcontrollers: you gain ability to compact heap. No more fragmentation.
That said, mostly I try not to dynamically allocate anything in firmware or kernel drivers. Whenever possible. Sometimes I write my own specialized allocators. For example a simple wait free allocator fast and rugged enough to call from an interrupt service routine.
C is the default and not a challenge on 8-bitters.
That's close enough in my book. Those MCUs are tricky targets and I can certainly live for example with not being able to pass structs as return values. Or without re-entrancy. Perfectly understandable once you take into account limited IRAM space, 128 or 256 bytes, where stack, register banks and most of your temporaries and globals need to reside.
Just in case you're actually trying to engage in good faith, though, I'll try this one more time. If I have a compiler that is less-than-100% standards compliant, I may not be able to use a few features of the standard. That means there may be a few ANSI C idioms that I can't use. Of those, the number that I would choose to use on that size of processor is very, very few. So in practice, there is no "challenge".
Why would I use very few of these features? Because on a processor that size, you're not writing a huge app. You don't use all the functions in the standard library, you don't use all the keywords, you usually don't push the language very far at all. At worst, you might have to develop one or two idioms of your own. It's... mildly annoying, rather than the big deal you're trying to make it.
| impl | c | py3 | mpy | pypy3 | cy3 |
|------|-------|--------|---------|-------|-------|
| [ns] | 0.176 | 11.462 | 37.633 | 0.818 | 0.590 |
| .c | 1.000 | 65.126 | 213.824 | 4.648 | 3.352 |
mpy - MicroPython
cy3 - Cython
So, ... low resource can't run heavy languages fast (yet?). Good thing is by using MicroPython and writing the time critical stuff in C you can get the best of both worlds while paying the least.
edit: sigh, markdown table
| impl | c | py3 | mpy | pypy3 | cy3 |
|------|-------|--------|---------|-------|-------|
| [ns] | 0.176 | 11.462 | 37.633 | 0.818 | 0.590 |
| .c | 1.000 | 65.126 | 213.824 | 4.648 | 3.352 |
Also, I'm taking a guess here and assuming that the values in the second line mean "execution time as multiples of the execution time for C".When you interoperate with another GCed language it's even harder, virtually impossible, because both languages' GCs assume they own everything and so anything that's visible in both languages will be freed twice.
Using GC languages doesn't mean doing 100% memory allocation via GC.
Others on that list have specific language features for GC free allocation.
There's lots of detail in the D language garbage collection docs:
https://dlang.org/spec/garbage.html
The whole thing might be instructive, but 28.3.3 has a bunch of particular expectations of the D GC.
The comments of jonathanstrange and humanrebar are also spot-on.
Of course, but at the cost of requiring a garbage collector. Mandatory GC has three main drawbacks:
* It makes it harder and much less convenient to call libraries in this language from other languages.
* Low-resource embedded systems are a no-go.
* GC is typically a tradeoff between speed and memory usage. Manual memory management can be very fast and very lean.