CTRL-D is the end of a character or byte stream for UNIX / Linux, and CTRL-Z is the end of a character or byte stream for Windows (a historical artifact from the earliest days of Microsoft DOS).
With the question code, as written, an empty line will not exit the loop because hasNextLine () will not evaluate to false. It will have a line terminator in the input byte stream.
System.in is a stream of bytes from standard input, usually a console. Therefore, stopping the byte stream stops the loop. Although nextLine () does not block waiting for input, hasNextLine () does. The only way the code ends, in the form in which it was designed, is with CTRL-Z on Windows or CTRL-D on UNIX / Linux, which ends the stream of bytes, calls hasNextLine () so as not to block waiting for input and return a boolean false, which ends the while loop.
If you want it to end with an empty line input, you can check for non-empty lines as part of the loop continuation condition. The following code demonstrates how to change the basic design of a question that uses hasNextLine () and nextLine () for one that exits if it receives an empty string or the end of an input character (i.e. CTRL-Z on Windows or CTRL-D on UNIX / Linux). Additional code in the while condition uses the function of assignment operators, in which they can be evaluated as an expression to return the assigned value. Since this is a String object, the String.equals () method can be used with evaluation.
Another additional code simply adds some printed result to make what happens obvious.
// HasNextLineEndDemo.java import java.util.*; public class HasNextLineEndDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); // this code is a bit gee-whiz // the assignment expression gets assigned sc.nextLine() // only if there is one because of the && // if hasNextLine() is false, everything after the && // gets ignored // in addition, the assignment operator itself, if // executed, returns, just like a method return, // whatever was assigned to str which, // as a String object, can be tested to see if it is empty // using the String.equals() method int i = 1; // input line counter String str = " "; // have to seed this to other than "" System.out.printf("Input line %d: ", i); // prompt user while (sc.hasNextLine() && !(str = sc.nextLine()).equals("")) { System.out.printf("Line %d: ", i); System.out.println("'" + str + "'"); System.out.printf("Input line %d: ", ++i); } // end while System.out.println("\nYOU'VE GOT THROUGH"); } // end main } // end class HasNextLineEndDemo