ImageIcon usa il Toolkit di AWT (java.awt.Toolkit) per caricare le immagini da file/url. In particolare, quel costruttore di ImageIcon usa il getImage di Toolkit. getImage utilizza un sistema di "caching" per cui a parità di filename/url restituisce lo stesso identico oggetto Image. Per dirlo in altro modo: una volta che getImage ha fornito un Image, alla prossima richiesta di quello stesso filename/url non rilegge/ricarica la immagine ma fornisce quella già in memoria.
Hai diverse possibilità:
1) Usare la classe javax.imageio.ImageIO (che tra l'altro supporta pure più formati). ImageIO fornisce in lettura un BufferedImage, dovresti poi incapsularlo nel ImageIcon. Nota importante: ImageIO carica la immagine in modo sincrono (bloccante) mentre il Toolkit carica in modo asincrono.
2) Usare direttamente il createImage di Toolkit, che non ha il meccanismo di caching. Ottieni quindi un Image che poi incapsuli in un ImageIcon.
3) Tenendo il caricamento con ImageIcon come hai fatto, invocare un flush() sul Image contenuto nel ImageIcon. Questo permette di "scaricare" i dati dalla cache e fa sì che la immagine venga materialmente ricaricata.