Observability of the Java Virtual Machine

Image
The JVM is one of the most observable runtimes. It provides us lots of tools for troubleshooting a JVM application in production. 1. Thread observability Threads are how the JVM actually does work. When something is wrong in production, the symptom is almost always a thread: stopped, blocked, leaking etc. Thread dumps work on any JVM with no  instrumentation, no agents, no restarts. <Example project link with /threaddump endpoint>         // (1) Deadlock — two threads grab the same pair of locks in opposite order.         new Thread(() -> grab(LOCK_A, LOCK_B), "deadlock-A-then-B").start();         new Thread(() -> grab(LOCK_B, LOCK_A), "deadlock-B-then-A").start(); http://localhost:8080/actuator/threaddump To list the JVMS, we can use the command below. PS C:\observe-jvm> jps -lv 25296 jdk.jcmd/sun.tools.jps.Jps -Dapplication.home=C:\Program Files\Microsoft\jdk-21.0.3.9-hotspot -Xms8m -Djdk.module.main=...

UTF-8 Validation in Java


A character in UTF8 can be from 1 to 4 bytes long, subjected to the following rules:
  • For 1-byte character, the first bit is a 0, followed by its unicode code.
  • For n-bytes character, the first n-bits are all one's, the n+1 bit is 0, followed by n-1 bytes with most significant 2 bits being 10.

Given an array of integers representing the data, lets calculate whether it is a valid utf-8 encoding.

Example:

data = [235, 140, 4], which represented the octet sequence: 11101011 10001100 00000100. 
Return false. 

The first 3 bits are all one's and the 4th bit is 0 means it is a 3-bytes character. The next byte is a continuation byte which starts with 10 and that's correct. But the second continuation byte does not start with 10, so it is invalid.

Source Code:

public static void main(String[] args) {

        // should be true
        System.out.println(validUtf8(new int[]{228, 189, 160, 229, 165, 189, 13, 10}));

        //should be false
         System.out.println(validUtf8(new int[]{240, 162, 138, 147, 145}));

        //should be true
        System.out.println(validUtf8(new int[]{197, 130, 1}));

        //should be false
        System.out.println(validUtf8(new int[]{235, 140, 4}));

        //should be false
        System.out.println(validUtf8(new int[]{255}));

        //should be false
        System.out.println(validUtf8(new int[]{250, 145, 145, 145, 145}));

    }


public static boolean validUtf8(int[] data) {

        int nOctetLeft = 0;

        for (int i = 0; i < data.length; ++i) {

            int octet = data[i];

            // n-byte character
            if ((octet & (1 << 7)) != 0) {

                int n = getCount(octet);

                if (n > 4) {
                    return false;
                }

                if (n > 1) {
                    if (nOctetLeft > 0) {
                        return false;
                    }

                    nOctetLeft += n;
                    --nOctetLeft;
                } else if (n == 1) {

                    --nOctetLeft;
                }
            } else {
                // one-byte character

                if (nOctetLeft != 0) {
                    return false;
                }
            }
        }

        // unsatisfied header
        if (nOctetLeft != 0) {
            return false;
        }

        return true;
    }

    private static int getCount(int octet) {
        int count = 0;
        int i = 7;
        while (i >= 0) {
            if ((octet & (1 << i)) == 0) {
                break;
            } else {
                ++count;
            }

            --i;
        }
        return count;
    }

Comments

Popular posts from this blog

The WeakReference class, monitoring memory leak and garbage collection in a Java application

Simplescalar Simulator - Part 2: sim-outorder.c

Notes on Java Performance