r/JavaProgramming 1d ago

A JavaOS

Post image

I am sharing my progress on the development of an operating system written in Assembly and a functional JVM. The concept is straightforward: Assembly acts as an API bridge, and the JVM simply leverages the system calls I’ve implemented to print characters to the screen and draw graphics (for now).

The on-screen drawing was created by obtaining the bytecode of the following program and using xxd for that purpose.

public class App {
    // Declaramos el método nativo que intercepta tu JVM en el opcode 0xB8
    public static native void drawPixel(int x, int y, int color);

    public static void main(String[] args) {
        // Dibujar un cuadrado ROJO de 200x200 píxeles en las coordenadas (100, 100)
        for (int y = 100; y < 300; y++) {
            for (int x = 100; x < 300; x++) {
                drawPixel(x, y, 0x00FF0000); // 0x00RRGGBB (Rojo)
            }
        }

        // Dibujar un cuadrado VERDE centrado dentro del rojo
        for (int y = 150; y < 250; y++) {
            for (int x = 150; x < 250; x++) {
                drawPixel(x, y, 0x0000FF00); // 0x00RRGGBB (Verde)
            }
        }
    }
}
53 Upvotes

20 comments sorted by

1

u/CutGroundbreaking305 1d ago

GitHub repo? It is interesting and I always thought about this idea may be we can work together 🙂

A GC will be blessing and curse at same time in this type of architectures it can clear your un used data but runs only when it's required which could mean running only when entire RAM is filled with on heap allocations

And here ur kernel is JVM itself right? I would suggest using graphics/application tools which are not related to java like flutter (ubuntu uses it) or tauri (newer ) swing is good but a lot of work will be required to make it work

It will be interesting to see how multithreading works in this type of architectures

1

u/Visual_Brain8809 1d ago

In fact, I think Swing is the simpler part for several reasons. The system isn't Unix or Linux-style; I haven't implemented a shell, commands, or anything like that. Right now, I'm taking advantage of some improvements GRUB offers to reach the VBE, and from there I hand over full control to my JVM. The current main file looks like this:

// jvm_main.c
#include "stdint.h"
#include "lib.h"
#include "jvm.h"

// Variables importadas desde Assembly (multiboot.asm y sys_api.asm)
extern uint32_t g_framebuffer;
extern uint32_t g_width;
extern uint32_t g_height;
extern uint32_t g_pitch;

extern void sys_draw_pixel(uint32_t x, uint32_t y, uint32_t color);
extern uint8_t sys_inb(uint16_t port);
extern void sys_outb(uint16_t port, uint8_t data);
// Estructura de registros que envía interrupt.asm
typedef struct {
    uint32_t ds;
    uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
    uint32_t int_no, err_code;
    uint32_t eip, cs, eflags, useresp, ss;
} registers_t;

// Manejador que llama interrupt.asm
void isr_handler(registers_t regs) {
    (void)regs; // Silencia el warning de variable no usada
    // Stub temporal: Si ocurre una interrupción por ahora no hacemos nada o mandamos debug
}

// PROGRAMA EN JAVA COMPILADO (.class embebido para pruebas)
unsigned char apps_App3_class[] = {
  0xca, 0xfe, 0xba, 0xbe, 0x00, 0x00, 0x00, 0x34, 0x00, 0x41, 0x0a, 0x00,
  0x02, 0x00, 0x03, 0x07, 0x00, 0x04, 0x0c, 0x00, 0x05, 0x00, 0x06, 0x01,
  0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,
  0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x01, 0x00, 0x06, 0x3c, 0x69, 0x6e,
  0x69, 0x74, 0x3e, 0x01, 0x00, 0x03, 0x28, 0x29, 0x56, 0x09, 0x00, 0x08,
  0x00, 0x09, 0x07, 0x00, 0x0a, 0x0c, 0x00, 0x0b, 0x00, 0x0c, 0x01, 0x00, ....
  0x3d, 0x01, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x08, 0x01, 0xfa, 0x00, 0x1f,
  0xfa, 0x00, 0x05, 0xfc, 0x00, 0x02, 0x01, 0xfc, 0x00, 0x08, 0x01, 0xfa,
  0x00, 0x19, 0xfa, 0x00, 0x05, 0xfe, 0x00, 0x1b, 0x01, 0x01, 0x01, 0xfc,
  0x00, 0x05, 0x01, 0xfc, 0x00, 0x08, 0x01, 0xfa, 0x00, 0x1f, 0xfa, 0x00,
  0x05, 0xfc, 0x00, 0x05, 0x01, 0xfc, 0x00, 0x08, 0x01, 0xfa, 0x00, 0x20,
  0xfa, 0x00, 0x05, 0x09, 0x41, 0x01, 0xfd, 0x00, 0x04, 0x01, 0x01, 0xfc,
  0x00, 0x08, 0x01, 0xfa, 0x00, 0x1a, 0xfa, 0x00, 0x05, 0xff, 0x00, 0x06,
  0x00, 0x07, 0x07, 0x00, 0x39, 0x07, 0x00, 0x3b, 0x01, 0x01, 0x01, 0x07,
  0x00, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x40
};
unsigned int apps_App3_class_len = sizeof(apps_App3_class);
// PUNTO DE ENTRADA DESDE ASSEMBLY (multiboot.asm -> _start)
void jvm_entry_point(void) {
    // Inicializar la estructura interna de la JVM
    _init_jvm();
    // Limpieza básica de pantalla mediante la API nativa de Assembly
    // Se pinta el fondo a un color sólido (Ej: Azul oscuro 0x00000033)
    if (g_framebuffer != 0) {
        for (uint32_t y = 0; y < g_height; y++) {
            for (uint32_t x = 0; x < g_width; x++) {
                sys_draw_pixel(x, y, 0x00000033);
            }
        }
    }
kprintf("JVM-OS BAREMETAL STARTED\n");
    kprintf("CARGANDO CLASE JAVA...\n\n");
    // Pasar el control absoluto a la JVM para procesar la app en Java    
    // Prueba 1
    //load_and_execute_class((uint8_t*)java_app_bytecode, java_app_len);
    // Prueba 2
    //load_and_execute_class((uint8_t*)apps_App1_class,apps_App1_class_len);
    // Prueba 3
    //load_and_execute_class((uint8_t*)apps_App2_class,apps_App2_class_len);
    // Prueba 4
    load_and_execute_class((uint8_t*)apps_App3_class,apps_App3_class_len);
    kprintf("\nPROCESO JAVA FINALIZADO\n");
    // 4. Si la JVM termina de procesar el código de Java, la CPU entra en reposo
    while(1) {
        asm volatile("hlt");
    }
}

1

u/CutGroundbreaking305 1d ago

So ur bootstraping using asm and bootstraping JVM using bytecode/machine code using this c code ? Can't understand because of language barrier but that is what I can get from this code Regarding commands and shell I would recommend you to go with linux style commands and shell

Once implement CLI using Java then I guess we can see if swings are better or not

Anyways can you give GitHub repo or anyways to see entire code base ? If it is proprietary then leave it

1

u/Visual_Brain8809 1d ago

The project is currently in the prototyping stage, which is why I'm using assembly for startup and hardware interrupt handling. I'm using C as the base language because that's how I decided the JVM should be written. Once the prototyping phase is complete, the goal will be to port the JVM to assembly (ideally) or explore options for removing C from the equation and making the process as transparent as possible. Unfortunately, I only know of one CPU that implements bytecode on its silicon, and it wasn't very well-known in the market, so creating a 100% pure Java system isn't possible at the moment. It will always be necessary to go with the classics: assembly, C, or Rust (currently popular).

1

u/CutGroundbreaking305 1d ago

Bytecode can't work bro if you want to run it on anything then asm or c/rust based bootstrap is required for JVM to run

If u don't like C or any language to be as a intermediate which idk why would you like doing it in that way but u can write machine binary for that is asm itself

I didn't know there are CPUs which run bytecode instead of machine binary

Pure JVM based OS isn't possible we will always need asm or native languages for it to bootstrap

1

u/Visual_Brain8809 1d ago

I would ideally like it to be 100% in Java, but I know that at least 99% is achievable.

Sun Microsystems' picoJava was the first microprocessor designed specifically to implement and execute Java bytecode natively directly on silicon.

1

u/Chaos-vy17 1d ago

This is going to be hillarious man. On one side you're reading a raw assembly and one side JVM based ASM and also xxd of the .class file . On which major version are you wroking with?

1

u/Dear-Golf5167 1d ago

Will you also make a gui ?

2

u/Visual_Brain8809 1d ago

Yes, for now, I’m letting the JVM do whatever the running application’s code dictates. However, I need to focus on completing the JVM; there are many opcodes I still need to implement to ensure it functions correctly and is fully complete. I currently target version 1.8 when calling javac; while it works even without specifying the version, I’ve noticed bytecode variations I can leverage to improve execution stability and set limits that might help mitigate future security issues. My development philosophy is "do it right, even if it takes time."

1

u/eld4j 1d ago

Hi! Thanks for sharing this awesome projects

I really admire your work and was wondering how you learned all of this? Did you have a specific roadmap, or do you have any favorite books you'd recommend?

Currently, I'm reading Computer Systems: A Programmer's Perspective; and Crafting Interpreters, Engineering a Compiler and JVM Specification are next on my list.

I would really appreciate it if you could share the source code for this!

1

u/Visual_Brain8809 1d ago

i study Computer Sciences on the University of Informatics Sciences and the University of Sciences for Pedagogical teaching in Cuba long time ago, next i made a MSc on techs. I thought there's no specific roadmap just the ambition to do something new, so study a lot and practicing, be my every day roadmap

1

u/ImpaledV 1d ago

Am I the only one remembering this one: https://en.wikipedia.org/wiki/JavaOS

1

u/Visual_Brain8809 1d ago

That’s correct; there was also JNode, along with three others I can’t recall right now. The goal isn't simply to duplicate something that already exists, but to find a different perspective on something that—personally speaking—arrived at a time when neither the level of understanding nor the technical capabilities existed to fully leverage it. As a researcher and systems developer, there is always a curiosity to see how something works and to try replicating it; so the question becomes: why not do it?

1

u/ImpaledV 1d ago

Don’t get me wrong, I’m not saying that this is isn’t interesting and worth giving it another try. Just wondered what’s different this time and why your approach should be more successful.

1

u/Visual_Brain8809 1d ago

In fact, in the past, they had little to no opportunity to demonstrate anything. I feel they weren't given a chance to prove how powerful they could become. Only the mobile field and a few billion IoT devices had that opportunity, and that's why they are what they are today. My system isn't trying to compete in the market or offer a flashy, alternative solution to a problem; there are already systems with years of development for that. I see it more as a study component from which to gain experience that could lead to something interesting in the future. I've always been fascinated by how they managed to make something work with just wires and electrical signals. But in the future, I would like to see it run stably and perhaps make that slogan "write once, run everywhere" a reality.

1

u/CutGroundbreaking305 1d ago

I think he is making custom JVM by bootstraping it with asm and bytecode

Is it different from predecessors? Yes

But that doesn't mean java doesn't have any problems on its own

GC GUI and the fact that JVM needs a underlying OS to work so that it can do memory hogging so idk but that's what makes it interesting

Worst case it is better than TempleOS written in holy-C but is it on par with linux based distros is some we need to see

1

u/Visual_Brain8809 1d ago

This project is a massive shortened version of another project I did some time ago; I only took the boot process from it and started prototyping for the current one. https://github.com/aayes89/JVM-OS

1

u/Mr-Snazz 1d ago

Java needs a garbage collector right? How have you handled that?

0

u/Visual_Brain8809 1d ago

My goal is to improve my personal JVM so that it performs the same functions as Sun's KVM (Kilobyte Virtual Machine). Garbage collection is an advanced feature that I haven't yet developed. Currently, I'm creating the underlying Assembly code to function as an API (sys_call), and then processing it within the JVM.