Sei parzialmente corretto. Java funziona basato su puntatori e tutte le variabili che puntano agli oggetti sono puntatori (chiamati ufficialmente riferimenti). La memoria di queste variabili è allocata sullo stack nel caso in cui siano definiti all'interno di un metodo o su heap se si tratta di campi.
Il valore dei dati stessi è come lo hai definito tu: tutti gli oggetti + primitive definite come campi, vivono su heap mentre le primitive definite all'interno dei metodi vivono sullo stack.
Nell'allocazione della memoria Java è praticamente la stessa sia per lo stack che per l'heap (diverso da C che ha una logica di allocazione più complessa per l'heap): per stack è solo push e per heap esiste un meccanismo chiamato bump del puntatore. La grande differenza sta nel recupero della memoria; per stack è jut pop mentre per heap c'è il rinomato garbage collector.
Una classe commentata più accurata sarebbe:
class HeapStack {
String str /*heap*/ = "test"; // heap memory
int a /*heap*/ = 10;// heap memory
private void Test() {
int a /*stack*/ = 10;// stack memory
String str /*stack*/ = "test";// heap memory
}
}