在CentOS 6上创建线程时Java进程内存不足
基本上,我在发出这个在CentOS 6上创建线程时Java进程内存不足,java,mysql,centos,threadpool,multiplayer,Java,Mysql,Centos,Threadpool,Multiplayer,基本上,我在发出这个nohup java-cp server.jar:mysql-connector.jar com.server.test.EchoMulti&后不到一个小时就出现了这个错误。错误: Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method)
nohup java-cp server.jar:mysql-connector.jar com.server.test.EchoMulti&
后不到一个小时就出现了这个错误。错误:
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Unknown Source)
at com.server.test.EchoMulti.main(EchoMulti.java:14)
我不熟悉服务器和Java。这是我在服务器上用Java做的第一件事,这是一款针对Android的多人游戏。游戏做得很好,所以有很多人尝试玩多人游戏。我已经修复了mySQL的max_连接,但是现在我遇到了whis问题。我还想知道是否有一种方法可以在出现导致崩溃的错误时自动重启进程。以及在重新启动时自动启动的方法
导致它的EchoMulti类:
package com.server.test;
import java.net.*;
import java.io.*;
public class EchoMulti {
public static void main(String[] args) throws IOException {
int portNumber = 25003;
boolean listening = true;
try (ServerSocket serverSock = new ServerSocket(portNumber)) {
while (listening) {
new EchoServer(serverSock.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + portNumber);
System.exit(-1);
}
}
}
EchoServer类:
package com.server.test;
import java.net.*;
import java.io.*;
import java.sql.*;
import java.lang.Thread;
public class EchoServer extends Thread {
private Socket sock = null;
public EchoServer(Socket sock) {
super("EchoServer");
this.sock = sock;
}
public void run(){
String url = "jdbc:mysql://IP:3306/DB";
String username = "USER";
String password = "PASSWORD";
Connection con = null;
Statement sta = null;
ResultSet resultSet = null;
try {
//System.out.println("Connecting database...");
con = DriverManager.getConnection(url, username, password);
//System.out.println("Database connected!");
} catch (SQLException e) {
throw new RuntimeException("Cannot connect the database!", e);
}
try (
PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
if(inputLine.equalsIgnoreCase("get")){
SEND SOMETHING
} else {
String catched[] = inputLine.split("\\;");
if(catched[0].equalsIgnoreCase("sub")){
SEND SOMETHING
} else if(catched[0].equalsIgnoreCase("res")){
SEND SOMETHING
}
}
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port 25003 or listening for a connection");
System.out.println(e.getMessage());
} finally {
//System.out.println("Closing the connection.");
if (con != null) try { con.close(); } catch (SQLException ignore) {}
try { sock.close(); } catch (IOException ignore) {} finally {}
}
}
public void close() throws IOException {
if (sock != null) sock.close();
}
}
您还可能在某个地方发生内存泄漏,或者阻止对已用内存进行正确的垃圾收集 我会做以下三件事 修改EchoServer类 您可以添加一个静态成员,以了解当崩溃发生时,内存中现有线程的数量是否是您期望的数量(应该与连接的播放器的数量相同) 如果有更多的线程比连接的球员是错误的 使用探查器使用探查器观察内存使用情况并确定瓶颈。还要确保没有“奇怪”的物体在几代人中幸存下来,或者在没有玩家数量增加的情况下,内存不会随着时间的推移而增加。NetBeans有一个很好的分析器,可以通过TCP连接到实时应用程序
使用-Xmx使用java-Xmx1g启动服务器 尝试增加Java应用程序的内存ram。我有一个VPS 1GHz、1GB ram和50GB的空间。也许我应该创建一个交换文件?关于RAM,你是对的:),但我设法减少了线程数。我用Java VisualVM检查了应用程序。以下是结果:。当线程开始下降时会发生错误。如果不运行jstatd,它将达到大约1000-1200。似乎记忆在一次又一次地消失。当我自由奔跑时,它几乎是满的。下面是错误日志。您的应用程序并不是因为内存不足而崩溃的……崩溃的是JVM本身。这可能发生在应用程序中的错误或系统资源被过度使用的情况下。在您的情况下,我怀疑有一个bug,因为您的分析会话中的堆只有256Mb,而您说您有1G的RAM。查看并检查它是否适合您的情况。无论如何,尝试使用Xmx和Xss来控制线程堆栈大小。我之前没有这样做,但现在当出现错误时,我得到了这样的结果:
Resource counter\u cpu\u share\u used red alert on environment mydomain.pl当前值:87软限制:85硬限制:95
该日志似乎与Plesk相关…I真的不知道:(
public class EchoServer extends Thread {
private Socket sock = null;
private static Integer CONNECTED = 0;
public EchoServer(Socket sock) {
try{
super("EchoServer");
this.sock = sock;
CONNECTED++;
} catch (Exception ex)
{
Logger.getLogger(EchoServer.class.getName()).log(Level.SEVERE, "Currently CONNECTED: "+CONNECTED);
}
}
.... your stuff here
@Override
public void finalize(){
super.finalize();
CONNECTED--;
}
}