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=...

Visitor Tasarım Kalıbını Hatırlayalım

Visitor kalıbına hangi durumda ihtiyaç duyabiliriz? Bir nesne yapısı üzerinde işlemler yapmak istiyoruz ve bu işlemlerin üzerinde çalıştığı nesne yapısından bağımsız olarak çeşitlenmesini istiyoruz. Bu durumda Visitor kalıbı işimize yarayabilir. Aşağıdaki örnekte bir arabanın parçaları üzerinde clean ve repair işlemleri yapılıyor:

public interface CarElement {
    void accept(CarElementVisitor visitor);
}

public interface CarElementVisitor {
    void visit(Engine engine);
    void visit(Wheel wheel);
}

public class Car implements CarElement {

    private Engine engine;
    private List wheels;

    public Car(Engine engine, Wheel... wheels) {
        this.engine = engine;
        this.wheels = Arrays.asList(wheels);
    }

    @Override
    public void accept(CarElementVisitor visitor) {
        engine.accept(visitor);
        for (Wheel wheel : wheels) {
            wheel.accept(visitor);
        }
    }
}

public class Engine implements CarElement {
    @Override
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}

public class Wheel implements CarElement {
    @Override
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}

public class CleaningVisitor implements CarElementVisitor {
    @Override
    public void visit(Engine engine) {
        System.out.println("Cleaning engine!");
    }

    @Override
    public void visit(Wheel wheel) {
        System.out.println("Cleaning wheel!");
    }
}

public class RepairingVisitor implements CarElementVisitor {
    @Override
    public void visit(Engine engine) {
        System.out.println("Repairing engine!");
    }

    @Override
    public void visit(Wheel wheel) {
        System.out.println("Repairing wheel!");
    }

    @Override
    public void visit(Car car) {
        System.out.println("Repairing car!");
    }
}

public class Program {

    public static void main(String[] args) {

        Engine engine = new Engine();
        Wheel wheel1 = new Wheel();
        Wheel wheel2 = new Wheel();

        Car car = new Car(engine, wheel1, wheel2);

        CarElementVisitor cleaningVisitor = new CleaningVisitor();
        CarElementVisitor repairingVisitor = new RepairingVisitor();

        car.accept(cleaningVisitor);
        car.accept(repairingVisitor);
    }

}

Burada Car sınıfına baktığımızda, üzerindeki "visit" işleminden haberdar fakat Cleaning ve Repairing gibi ayrıntılardan habersiz. Yani, kendi nesne yapısı üzerinde işlemlerin yapılabilmesini sağlıyor ve hatta hangi parçaları üzerinde işlemlerin yapılacağını belirliyor. Fakat işlemlerin somut sınıflarına bağımlı değil. Sadece CarElementVisitor arayüzüne bağımlı. 
Visitor sınıfları ise, Car sınıfının parçaları üzerinde yapılacak işlemin ayrıntılarını biliyor. 


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