Jsch SFTP 客户端无法创建新的本机线程
Jsch SFTP client unable to create new native thread
我使用 Jsch 作为 SFTP 客户端从远程 SFTP 目录读取和写入 XML 文件。
我用了 5 秒的工作来检查是否有新文件可用于草稿,在 30 或 40 分钟循环后我收到以下错误
Caused by: java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method) [rt.jar:1.7.0_65]
at java.lang.Thread.start(Thread.java:714) [rt.jar:1.7.0_65]
at com.jcraft.jsch.Session.connect(Session.java:528) [jsch-0.1.53.jar:]
at com.jcraft.jsch.Session.connect(Session.java:183) [jsch-0.1.53.jar:]
这是用于创建连接的源代码
public InputStream getFile(String path){
Session session = null;
Channel channel = null;
try {
ChannelSftp sftp = openConnexion(session, channel);
return sftp.get(path);
} catch (SftpException e) {
new RuntimeException("Error detected during get file from SFTP specific path : " + e.getMessage(), e);
} finally {
closeConnexion(session, channel);
}
}
private ChannelSftp openConnexion(Session session, Channel channel) {
try {
JSch ssh = new JSch();
session = ssh.getSession("user", "hostname", 22);
session.setPassword("password");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
channel = session.openChannel(SFTP_CHANNEL);
channel.connect();
ChannelSftp sftp = (ChannelSftp) channel;
return sftp;
} catch (JSchException e) {
throw new RuntimeException("Error detected during open SFTP connexion : " + e.getMessage(), e);
}
}
private void closeConnexion(Session session, Channel channel) {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
我尝试增加 JVM 线程堆栈的大小并增加 unix 允许的本机进程限制 => 同样的错误。
我使用了以下命令来做到这一点:
ulimit -u unlimited
我尝试创建一个jsch session池,jsch session在没有断开的情况下是不可用=> "SFTP Error 4"
我的作业运行到部署在 jboss-as-7 上的 war,这是 JVM 选项:
JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxPermSize=256m -Xss1024k"
您对这种治疗有什么建议吗?
谢谢!
问题是您没有在每次循环后关闭通道和会话,这至少会泄漏用于通过 SFTP 执行下载的线程。
尝试在 finally 块中关闭会话和通道(如果有效)会使您尝试读取的 InputStream 无效;阻止您正确处理文件。
我将稍微重构代码,这应该可以解决资源耗尽问题,并附注:
// session and channel are at the object scope
Session session = null;
Channel channel = null;
public InputStream getFile(String path){
// First, close any existing connections.
try {
closeConnexion();
} catch (SftpException e) {
// You can try to handle an issue here; but it's
// probably not worth it
}
try {
ChannelSftp sftp = openConnexion();
return sftp.get(path);
} catch (SftpException e) {
new RuntimeException("Error detected during get file from SFTP specific path : " + e.getMessage(), e);
} finally {
}
}
private ChannelSftp openConnexion() {
try {
JSch ssh = new JSch();
// use the object's session variable
session = ssh.getSession("user", "hostname", 22);
session.setPassword("password");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
// use the object's channel object
channel = session.openChannel(SFTP_CHANNEL);
channel.connect();
ChannelSftp sftp = (ChannelSftp) channel;
return sftp;
} catch (JSchException e) {
throw new RuntimeException("Error detected during open SFTP connexion : " + e.getMessage(), e);
}
}
private void closeConnexion() {
// close object's channel and session
if (channel != null) {
channel.disconnect();
channel = null;
}
if (session != null) {
session.disconnect();
session = null;
}
}
如果我要重新设计它,我会 return 一个容器 class 而不是包含通道、会话和 InputStream 的 InputStream。容器 class 将有一个 'close' 方法,该方法将关闭 InputStream、通道和会话,然后我不会将通道和会话存储在对象中。
我使用 Jsch 作为 SFTP 客户端从远程 SFTP 目录读取和写入 XML 文件。
我用了 5 秒的工作来检查是否有新文件可用于草稿,在 30 或 40 分钟循环后我收到以下错误
Caused by: java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method) [rt.jar:1.7.0_65]
at java.lang.Thread.start(Thread.java:714) [rt.jar:1.7.0_65]
at com.jcraft.jsch.Session.connect(Session.java:528) [jsch-0.1.53.jar:]
at com.jcraft.jsch.Session.connect(Session.java:183) [jsch-0.1.53.jar:]
这是用于创建连接的源代码
public InputStream getFile(String path){
Session session = null;
Channel channel = null;
try {
ChannelSftp sftp = openConnexion(session, channel);
return sftp.get(path);
} catch (SftpException e) {
new RuntimeException("Error detected during get file from SFTP specific path : " + e.getMessage(), e);
} finally {
closeConnexion(session, channel);
}
}
private ChannelSftp openConnexion(Session session, Channel channel) {
try {
JSch ssh = new JSch();
session = ssh.getSession("user", "hostname", 22);
session.setPassword("password");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
channel = session.openChannel(SFTP_CHANNEL);
channel.connect();
ChannelSftp sftp = (ChannelSftp) channel;
return sftp;
} catch (JSchException e) {
throw new RuntimeException("Error detected during open SFTP connexion : " + e.getMessage(), e);
}
}
private void closeConnexion(Session session, Channel channel) {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
我尝试增加 JVM 线程堆栈的大小并增加 unix 允许的本机进程限制 => 同样的错误。
我使用了以下命令来做到这一点:
ulimit -u unlimited
我尝试创建一个jsch session池,jsch session在没有断开的情况下是不可用=> "SFTP Error 4"
我的作业运行到部署在 jboss-as-7 上的 war,这是 JVM 选项:
JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxPermSize=256m -Xss1024k"
您对这种治疗有什么建议吗?
谢谢!
问题是您没有在每次循环后关闭通道和会话,这至少会泄漏用于通过 SFTP 执行下载的线程。
尝试在 finally 块中关闭会话和通道(如果有效)会使您尝试读取的 InputStream 无效;阻止您正确处理文件。
我将稍微重构代码,这应该可以解决资源耗尽问题,并附注:
// session and channel are at the object scope
Session session = null;
Channel channel = null;
public InputStream getFile(String path){
// First, close any existing connections.
try {
closeConnexion();
} catch (SftpException e) {
// You can try to handle an issue here; but it's
// probably not worth it
}
try {
ChannelSftp sftp = openConnexion();
return sftp.get(path);
} catch (SftpException e) {
new RuntimeException("Error detected during get file from SFTP specific path : " + e.getMessage(), e);
} finally {
}
}
private ChannelSftp openConnexion() {
try {
JSch ssh = new JSch();
// use the object's session variable
session = ssh.getSession("user", "hostname", 22);
session.setPassword("password");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
// use the object's channel object
channel = session.openChannel(SFTP_CHANNEL);
channel.connect();
ChannelSftp sftp = (ChannelSftp) channel;
return sftp;
} catch (JSchException e) {
throw new RuntimeException("Error detected during open SFTP connexion : " + e.getMessage(), e);
}
}
private void closeConnexion() {
// close object's channel and session
if (channel != null) {
channel.disconnect();
channel = null;
}
if (session != null) {
session.disconnect();
session = null;
}
}
如果我要重新设计它,我会 return 一个容器 class 而不是包含通道、会话和 InputStream 的 InputStream。容器 class 将有一个 'close' 方法,该方法将关闭 InputStream、通道和会话,然后我不会将通道和会话存储在对象中。