Mi sembra che qui si stia facendo un po' di confusione.

In primo luogo, una variabile locale in sé viene distrutta quando esce di scope. Per cui, se vuoi limitare l'esistenza di una variabile ti basta inserirla in uno scope ristretto:
codice:
public void metodo()
{
    { // apro un nuovo blocco
        int i=10; // i è locale a questo blocco più interno
        ....
    } // qui i smette di esistere
    {
        int i=25; // questa i è un'altra variabile rispetto alla precedente
        ...
    }
}
Tutto questo ovviamente è puramente concettuale e in sé non ha una particolare differenza rispetto a riassegnare 25 a i, dato che alla fin della fiera la "nuova" i con ogni probabilità andrà a riciclare lo spazio sullo stack della precedente.

Fin qui il garbage collector non c'entra assolutamente nulla, sono semplicemente regole di scoping.

Ora, il punto è: cosa è contenuto esattamente in una variabile?

Dipende dal tipo.

In Java ci sono due categorie di tipi: i tipi primitivi e "tutti gli altri" (con abuso di terminologia da .NET li chiamerei "i value type" e i "reference type").

I tipi primitivi sono sostanzialmente vari tipi di numeri; quando dichiari una variabile di un tipo primitivo, essa contiene effettivamente il valore che ci memorizzi, e la sua esistenza si conclude completamente nel momento in cui essa esce di scope.

I "reference types", invece, sono classi, enum & co (tutto il resto, in sostanza). Quando tu dichiari una variabile di un tipo "reference type" in realtà stai dichiarando un riferimento (che può anche essere nullo) ad un oggetto di quel tipo, quello che in C sarebbe un puntatore. La differenza è evidente ad esempio nell'inizializzazione:
codice:
int i = 10;
UnTipo t = new UnTipo();
nel primo caso stai copiando direttamente il valore in i, nel secondo crei con new un oggetto di tipo UnTipo in un'area di memoria separata (l'heap) e inizializzi t con un riferimento all'oggetto appena creato.

Ora, con i reference types la questione è più complicata rispetto ai tipi primitivi, dato che è possibile avere più variabili che hanno un riferimento allo stesso oggetto, per cui, anche se una variabile esce di scope o le viene assegnato un altro riferimento ad oggetto, è possibile che un'altra continui ad avere un riferimento al medesimo oggetto. In linguaggi senza garbage collection questo è un problema non indifferente, in Java la questione è semplificata con il GC.
Infatti quando una variabile di tipo reference esce di scope la variabile in sé viene distrutta, ma l'oggetto a cui punta continua ad esistere per il motivo spiegato sopra. Ovviamente se si andasse avanti indefinitamente a creare oggetti senza distruggerli prima o poi finirebbe la memoria disponibile.

Il trucco è che ciclicamente viene fatto partire il GC, che altro non è che una parte della JVM che (semplificando) passa in rassegna tutti gli oggetti creati e vede se nel programma in esecuzione ci sono ancora variabili che si riferiscono ad essi. Dopo aver effettuato i controlli del caso, gli oggetti che non hanno più riferimenti vengono eliminati, e la memoria che occupavano resa disponibile per nuovi oggetti.

Nota però che tutto questo non ha alcuna influenza con il caso che hai specificato, dato che stai parlando di una variabile di tipo int, che non è gestita dal GC e cessa di esistere appena finisce il blocco in cui è dichiarata.