Either use byte code analysis or time the two approaches using System.nanoTime. I think second one is faster. here is what I did to conclude this:
I wrote three classes as given below:
public static class A {
    public B b = new B();
}
public static class B {
    public E e = new E();
}
public static class E {
    public String name = "s";
    public int age = 1;
}
Then I wrote two simple methods and get their java byte code using javap -c CLASS_NAME.
public static void Test1() {
    A a = new A();
    String str = a.b.e.name;
    int age = a.b.e.age;
}
The byte code of above method is:
public static void Test1();
    Code:
       // new A();
       0: new           #15
       3: dup           
       4: invokespecial #17                 
       7: astore_0      
       8: aload_0
       // a.b (it accesses the field and put it on operand stack)
       9: getfield      #18
      // b.e
      12: getfield      #22
      // b.name
      15: getfield      #28
      // pop 'name' from stack
      18: astore_1      
      19: aload_0  
      // cyle continues     
      20: getfield      #18
      23: getfield      #22
      26: getfield      #34 
      29: istore_2      
      30: return
You can clearly see at byte code level, each time you try to access field, it put the value of that filed on stack and then this cycle continues. Therefore, a.a1.a2....an would be n instruction if stack would have enough spae to hold all n. And there was no optimisation by compiler this same cycle of called again to access both name and age field.
Now here is the second method:
public static void Test2() {
        A a = new A();
        E e = a.b.e;
        String str = e.name;
        int age = e.age;
    }
Byte code for above method is:
public static void Test2();
    Code:
       // new A();
       0: new           #15 
       3: dup           
       4: invokespecial #17
       7: astore_0      
       8: aload_0       
       // store a.b.e on operand stack once
       9: getfield      #18
      12: getfield      #22
      15: astore_1      
      16: aload_1
      // get 'name' field
      17: getfield      #28
      20: astore_2      
      21: aload_1       
      // get 'age' field
      22: getfield      #34
      25: istore_3      
      26: return        
Above is 4 instruction shorter than previous code as it prevents execution of getfield. So I think this should be faster than previous one.