When getKeys() exits and its stack is forgotten, or at least when the next function call is executed by the same thread that executes getKeys(), the reference, vString, will probably be overwritten. Granted that the Vector vString refers to lives on the heap, is it not subject to garbage collection anytime after getKeys() exits? How can the user be sure that the Enumeration<String> that getKeys() returns will actually iterate over anything useful? The demo program that the book author offers does work though.

is it not subject to garbage collection anytime after getKeys() exits?

Depends on what is still referring to it. In this case, the Enumeration is, so it won't be garbage collected.

How can the user be sure that the Enumeration<String> that getKeys() returns will actually iterate over anything useful?

Since the Enumeration is still referring to the Vector, it'll iterate (or rather enumerate) over it quite well. It would be ridiculous if the data disappeared like this.
Garbage collection doesn't collect things that are still being used.

Or stating that in a different way.
1. Once computed (step before the last bullet) the value must be held somewhere.
2. That somewhere is considered an active reference by the GC.
3. So it can't be collected before the last bullet point arrives.