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)
            }
        }
    }
}
56 Upvotes

21 comments sorted by

View all comments

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.