Это зависит от того, что Вы подразумеваете под исчерпыванием памяти.
, Когда malloc()
сбои в большинстве систем, это - потому что у Вас закончилось адресное пространство.
, Если большая часть той памяти взята cacheing, или mmap'd регионами, Вы могли бы быть в состоянии исправить часть его путем освобождения кэша или unmmaping. Однако это действительно требует, чтобы Вы знали то, что Вы используете ту память для - и поскольку Вы заметили, что или большинство программ не делает, или это не имеет значения.
, Если Вы использовали setrlimit()
на себе (чтобы защитить от непредвиденных нападений, возможно, или возможно базироваться сделал это Вам), можно ослабить предел в обработчике ошибок. Я делаю это очень часто - после запроса пользователя, если это возможно, и входа события.
, С другой стороны, ловя переполнение стека является немного более трудным, и не является портативным. Я записал posixish решение для ECL и описал реализацию Windows, если Вы идете этим путем. В этом зарегистрировались ECL несколько месяцев назад, но я могу вскопать исходные патчи, если Вам интересно.
Прежде всего, я повторяю мнение других о том, что повторное изобретение колеса здесь, скорее всего, приведет к множеству проблем для вас. Однако, если вы все равно хотите пойти по этому пути, то, что вы пытаетесь сделать, нетрудно. Вы экспериментировали с Jetty?
Может быть, что-то вроде этого:
public class MyWebServer {
public void foo() throws IOException {
while (true) {
//block here until a connection request is made
ServerSocket socket = new ServerSocket();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
MyRequest request = new MyRequest(socket);
request.addResumeListener(new ResumeListener() {
public void resume() {
locker.notify();
}
});
synchronized(locker){
//create a new thread for each request
Thread thread = new Thread(request);
//start() the thread - not run()
thread.start();
//this thread will block until the MyRequest run method calls resume
locker.wait();
}
} catch (Exception e) {
}
}
}
}
public interface ResumeListener {
public void resume();
}
public class MyRequest implements Runnable{
private ResumeListener resumeListener;
public MyRequest(ServerSocket socket) {
}
public void run() {
// do something
resumeListener.resume(); //notify server to continue accepting next request
}
public void addResumeListener(ResumeListener rl) {
this.resumeListener = rl;
}
}
You probably need to use a Java Condition. From the docs:
Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true.
Run under a debugger and set a breakpoint?
If unfeasible, then read a line from System.in?
You can use java.util.concurrent.CountDownLatch with a count of 1 for this. Arrange for an instance of it to be created and shared by the parent and child thread (for example, create it in HttpRequest
's constructor, and have it retrievable by a member function). The server then calls await()
on it, and the thread hits countDown()
when it's ready to release its parent.