Object level lock vs Class level lock in Java?

Both Object level lock and Class level lock are used to achieve synchronization mechanisms in a multi-threaded application.
Every object in Java has a unique lock. If a thread wants to execute a synchronized method on a given object, first it has to get a lock of that object. Once thread got the lock then it is allowed to execute any synchronized method on that object. Once method execution completes automatically thread releases the lock. Acquiring and release lock internally is taken care of by the JVM. Object level lock is a mechanism when we want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on a given instance of the class. This can always be done to make instance-level data thread-safe.
public class ObjectLevelLockTest implements Runnable {
   @Override
   public void run() {
      objectLock();
   }
   public void objectLock() {
      System.out.println(Thread.currentThread().getName());
      synchronized(this) {
         System.out.println("Synchronized block " + Thread.currentThread().getName());
         System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
      }
   }
   public static void main(String[] args) {
      ObjectLevelLockTest test1 = new ObjectLevelLockTest();
      Thread t1 = new Thread(test1);
      Thread t2 = new Thread(test1);
      ObjectLevelLockTest test2 = new ObjectLevelLockTest();
      Thread t3 = new Thread(test2);
      t1.setName("t1");
      t2.setName("t2");
      t3.setName("t3");
      t1.start();
      t2.start();
      t3.start();
   }
}
t1
t2
t3
Synchronized block t1
Synchronized block t3
Synchronized block t1 end
Synchronized block t3 end
Synchronized block t2
Synchronized block t2 end
Every class in Java has a unique lock which is nothing but a class level lock. If a thread wants to execute a static synchronized method, then thread requires a class level lock. Once a thread got the class level lock, then it is allowed to execute any static synchronized method of that class. Once method execution completes automatically thread releases the lock. The Class level lock prevents multiple threads to enter in a synchronized block in any of all available instances on runtime.
public class ClassLevelLockTest implements Runnable {
   @Override
   public void run() {
      classLock();
   }
   public void classLock() {
      System.out.println(Thread.currentThread().getName());
      synchronized(ClassLevelLockTest.class) {
         System.out.println("Synchronized block " + Thread.currentThread().getName());
         System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
      }
   }
   public static void main(String[] args) {
      ClassLevelLockTest test1 = new ClassLevelLockTest();
      Thread t1 = new Thread(test1);
      Thread t2 = new Thread(test1);
      ClassLevelLockTest test2 = new ClassLevelLockTest();
      Thread t3 = new Thread(test2);
      t1.setName("t1");
      t2.setName("t2");
      t3.setName("t3");
      t1.start();
      t2.start();
      t3.start();
   }
}
t3
t2
t1
Synchronized block t3
Synchronized block t3 end
Synchronized block t2
Synchronized block t2 end
Synchronized block t1
Synchronized block t1 end