During compilation the compiler knows that B is dependant on A. It passes the same data to the JVM. During loading phase of class B, the JVM reads metadata sent by the compiler and finds out that B is dependant on A and hence loads (and runs static initializers) of A then continues to load B and then initializes B. 
If we had 2 classes Sample and Test extends Sample the Class Constant Pool (part of byte code ) for Test would have :
Constant pool:
   #1 = Class              #2             //  Test
   #2 = Utf8               Test
   #3 = Class              #4             //  Sample <---- reference
   #4 = Utf8               Sample
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          //  Sample."<init>":()V   <-- init Sample
   #9 = NameAndType        #5:#6          //  "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               LTest;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               SourceFile
  #19 = Utf8               Sample.java
If you run java with verbose:class option then grep it, you will be able to see that the dependant class is being loaded.
java -verbose:class Test | grep 'Sample'
[Loaded Sample from file:/Users/XXXX/Workspaces/SampleTest/Sample/bin/] <== Sample loaded first because test depends on Sample.
[Loaded Test from file:/Users/XXXX/Workspaces/SampleTest/Sample/bin/]