Java应用程序和AMD处理器问题
我们有一个windows应用程序,它在WindowsXP、7、8、8.1上进行了测试。应用程序由两部分组成:引导程序和主应用程序。引导确保主应用程序的更新,并在特定点更新主应用程序。但是用户可以通过任务管理器Ctrl+Shift+ESC->进程强制停止Boostrap进程,方法是杀死一个名为javaw的进程。在这种情况下,主应用程序将不会更新,旧版本将启动。为了避免这样的问题,我们通过套接字引入了引导程序和主应用程序的接口。以下是引导启动时的VM参数: javaw.exe-Xms75M-Xmx90M-Xincgc-jar bootstrap.jar 引导程序中有一个SocketServer类:Java应用程序和AMD处理器问题,java,sockets,intel,serversocket,Java,Sockets,Intel,Serversocket,我们有一个windows应用程序,它在WindowsXP、7、8、8.1上进行了测试。应用程序由两部分组成:引导程序和主应用程序。引导确保主应用程序的更新,并在特定点更新主应用程序。但是用户可以通过任务管理器Ctrl+Shift+ESC->进程强制停止Boostrap进程,方法是杀死一个名为javaw的进程。在这种情况下,主应用程序将不会更新,旧版本将启动。为了避免这样的问题,我们通过套接字引入了引导程序和主应用程序的接口。以下是引导启动时的VM参数: javaw.exe-Xms75M-Xmx9
public class Provider {
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
public Provider() {
}
public void run() {
try{
providerSocket = new ServerSocket(54345);
connection = providerSocket.accept();
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
do {
try {
message = (String)in.readObject();
if (message.equals("bye")) {
sendMessage("bye");
}
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(IOException ioe) {
ioe.printStackTrace();
} finally {
try {
in.close();
out.close();
providerSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
public void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public void stop() {
if (providerSocket != null && in != null && out != null && !providerSocket.isClosed()) {
try {
in.close();
out.close();
providerSocket.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
主应用程序是通过ProcessBuilder引导启动的,如下所示:
public static void communicate(Process process) {
final BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("Windows-1251")));
final BufferedReader stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream(), Charset.forName("Windows-1251")));
//InputStream
new Thread() {
@Override
public void run() {
String line;
try {
while ((line = stdOut.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdOut.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
//ErrorStream
new Thread() {
@Override
public void run() {
String line;
try {
while ((line = stdErr.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdErr.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
try {
final Provider provider = new Provider();
ExecutorService pEexec = Executors.newCachedThreadPool();
Future<Void> FPExec = pEexec.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
provider.run();
}
return null;
}
});
pEexec.shutdown();
process.waitFor();
debugOut("[MainApp] Exit");
provider.stop();
FPExec.cancel(true);
debug("Destroy process");
process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void startApp() {
try {
ArrayList<String> params = new ArrayList<String>();
...
params.add("-Xms32M");
params.add("-Xmx48M");
params.add("-Xincgc");
params.add("-cp");
params.add(new File(pathToJar, "mainapp.jar").getPath());
params.add("net.craftwork.mainapp.AppStart");
params.add(licCode());
ProcessBuilder procBuild = new ProcessBuilder(params);
debugOut("[MainApp] Start");
Process proc = procBuild.start();
communicate(proc);
} catch (Exception e) {
e.printStackTrace();
}
}
我相信这就是全部。即使在速度较慢的计算机上,整个设置也运行得非常好。问题是,在引入套接字接口之后,我们收到了一些用户的投诉,报告了崩溃。我们花了一些时间来解决这个问题,但我们发现:采用英特尔处理器的计算机非常好,只有采用AMD处理器的计算机才会崩溃。崩溃通常发生在启动后3到15分钟内。当崩溃发生时,计算机的资源并没有得到充分利用,处理器的工作负载约为20-50%,RAM也相当空闲。当崩溃发生时,用户只能使用硬件重置或电源按钮重置计算机,其他任何操作都不会响应。所有用户都拥有最新的JAVA 1.7.0_51。无论系统是32位还是64位,如果它是基于Intel的,则系统都会崩溃或不崩溃。请分享你的想法。可能有人有相同的问题,可以帮我解决。什么会导致它崩溃?当它崩溃时捕获异常,记录该异常的调用堆栈,检查该异常以找出它崩溃的行,检查代码以找出它在该行上做了什么,修复它。或者,如果您无法修复它,请返回给我们一个更具体的问题,关于为什么在这种情况下,该行出现问题。当然,我们会记录所有内容。在主应用程序中,所有日志都发送到System.out,引导程序捕获主应用程序的所有事件,并通过System.setOut将所有内容记录到日志文件中。但是我们这里有一个系统的全站,当所有的服务都关闭,整个系统没有响应时,因此我们不仅不能获取应用程序的日志,也不能获取系统日志,在崩溃期间,甚至没有写入Windows日志。系统重新启动后,我们得到的第一个日志条目是system was reboot。因此,我们没有任何关于代码哪一部分导致问题的额外信息。唯一的线索是,如果我们在主应用程序的Bootstrap和Requester.main中删除SocketServer start的线程,AMD系统不会遇到此类问题。再一次,英特尔系统根本没有遇到任何问题,问题只出现在AMD系统上。这可能与著名的Livelock错误有关-请参阅
public class Requester {
Socket requestSocket;
ObjectOutputStream out;
ObjectInputStream in;
String message;
static Future<Void> oExec;
Requester() {
}
void run() {
try {
requestSocket = new Socket("localhost", 54345);
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
do {
try {
message = (String)in.readObject();
sendMessage("bye");
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(UnknownHostException uhe) {
uhe.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
oExec.cancel(true);
CommonUtils.debug("Bootstrap not found. Exit.");
System.exit(0);
} finally {
try {
in.close();
out.close();
requestSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public static void main() {
final Requester client = new Requester();
ExecutorService exec = Executors.newCachedThreadPool();
oExec = exec.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
client.run();
Thread.sleep(1000);
}
return null;
}
});
exec.shutdown();
}
}
public class AppStart {
public static void main(final String[] args) {
Requester.main();
EventQueue.invokeLater(new Runnable() {
public void run() {
...
}
});
}
}