Why is the role of the StoreStore memory Barrier inserted by final different from that of volatile?

premise:
when watching the volatile section of "the Art of Java concurrent programming", there is a sentence:

StoreStore Barrier ensures that all normal writes preceding it are visible to any processor before volatile is written.

scenario:

public class FinalExample{
    int i;
    final int j;
    public FinalExample(){
        i = 1;
        j = 2;  //JMMfinal StoreStore
    }
}

question:
Why is StoreStore Barrier also inserted, and the variable I that precedes StoreStore may still be reordered outside the constructor and not visible to other threads ? But the volatile in the premise can?

the following is a personal guess, but not so sure: when the
compiler encounters the volatile keyword, it ensures that the normal write before the volatile write has been completed and is visible to other threads (compiler reordering does not occur). Final has no compiler guarantee, so compiler reordering occurs.

I hope some great god can answer this. Thank you

Mar.07,2021
MySQL Query : SELECT * FROM `codeshelper`.`v9_news` WHERE status=99 AND catid='6' ORDER BY rand() LIMIT 5
MySQL Error : Disk full (/tmp/#sql-temptable-64f5-1ea05b2-1acf.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
MySQL Errno : 1021
Message : Disk full (/tmp/#sql-temptable-64f5-1ea05b2-1acf.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
Need Help?