Note that to "crash" means to exit abruptly, so the program's no longer running. To "freeze" means to stop working, so that the program won't respond to input anymore. Your program is freezing, not crashing!
Anyway: accept() waits for a new connection to come in before returning, right? Well, you're using invokeLater() to call accept() directly on the event-processing thread, which is also responsible for painting the screen and responding to mouse clicks. As long as accept() is waiting for a connection, your GUI will be frozen. Never call any method that will take a long time to run on the event thread, or it will freeze your GUI.
Even worse, you're running it on the event thread many, many, many times! invokeLater() returns immediately, so your while loop is adding calls to accept() onto the event thread at the rate of many thousands per second! Finally, note that you don't need to -- in fact, can't! -- create a new ServerSocket for each accept() call;
you should create just one, and call accept on it in a loop, once for each client.
Anyway, to fix your problem: don't call accept() on the event loop! It looks like you already know how to define a Runnable and create a thread. Do that -- create a separate thread just for calling accept() and servicing clients. Create the ServerSocket
outside of that loop.