There are several ways to do this.
First, code that runs at the "OS level" does not have to be written in the same language as the OS. It just needs to be associated with the OS code. Almost all languages can interact with C, and that’s really all that is needed.
So, in terms of language, technically there is no problem. Java functions can call C functions, and C functions can call Java functions. And if the OS is not written in C (say, for the sake of an argument written in C ++), then the C ++ OS code can call some intermediate C code, which is sent to your Java, and vice versa. C is pretty much a programming language.
Once a program has been compiled (for native code), its source language no longer matters. Assembler looks about the same, regardless of what language the source code was written before compilation. As long as you use the same calling convention as the OS, this is not a problem.
A bigger problem is runtime support. There are not many software services in the OS. For example, there is usually no Java virtual machine. (There is no reason why it could not technically be there, but usually, but usually, we can safely assume that it is not present).
Unfortunately, in its default Java bytecode view, a Java program requires a lot of infrastructure. He needs a Java virtual machine to interpret and JIT bytecode, and he needs a class library, etc.
But there are two ways around this:
- Java support in the kernel. This will be an unusual step, but it can be done.
- Or compile the Java source code in a native format. A Java program does not need to be compiled into Java bytecode. You can compile it for x86 assembler. The same goes for any class libraries that you use. They can also be compiled to assembler. Of course, parts of the Java class library require certain OS functions that will not be available, but then the use of these classes could be avoided.
So yes, it can be done. But it is not simple, and it is not clear what you received.
Of course, another problem may be that Java will not allow you to access arbitrary places of memory, which will greatly complicate the transfer of hardware. But this could also be handled, perhaps by calling very simple C functions that simply return the corresponding memory areas as arrays for Java to work.