I am writing an application that copies files from a Samba share using the JCIFC Java CIFS Client Library (which, btw, is a very helpful, widely used, and well developed project).
As usual I am under the gun to get something up and running so I do not have the luxury to explore all of the details as much as I would like. My application gets a directory listing of a Samba share and then spawns a new thread for each new file (with a limit, of course) which copies the file to the local file system via a SmbFileInputStream and FileOutputStream as follows (without the obligatory try/catch blocks for readability):
(An SmbFile instance is provided by the calling code)
byte[] readBuffer = new byte[1024];
int bytesRead = 0;
File fileDestination = new File(“/tmp/”, “destinationFile”);
FileOutputStream fileDestinationFOS = new FileOuputStream(fileDestination);
SmbFileInputStream smbFIS = new SmbFileInputStream(smbFile);
while ((bytesRead = smbFIS.read(readBuffer)) != -1 ) {
fileDestination.write(readBuffer, 0, bytesRead);
}
smbFIS.close();
fileDestinationFOS.close();
When I run it I get the following Exception:
Exception in thread “Thread-3” java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:614)
at jcifs.UniAddress.lookupServerOrWorkgroup(UniAddress.java:173)
at jcifs.UniAddress.getAllByName(UniAddress.java:290)
at jcifs.UniAddress.getByName(UniAddress.java:245)
at jcifs.smb.Dfs.getTrustedDomains(Dfs.java:62)
at jcifs.smb.Dfs.resolve(Dfs.java:167)
at jcifs.smb.SmbFile.resolveDfs(SmbFile.java:671)
at jcifs.smb.SmbFile.send(SmbFile.java:773)
at jcifs.smb.SmbFileInputStream.readDirect(SmbFileInputStream.java:181)
at jcifs.smb.SmbFileInputStream.read(SmbFileInputStream.java:142)
at jcifs.smb.SmbFileInputStream.read(SmbFileInputStream.java:132)
at com.ngc.amap.mapDaemon.FileScanDaemon$RemoteFileCopier.run(FileScanDaemon.java:461)
at java.lang.Thread.run(Thread.java:636)
After considerable searching and testing I determined that the call to jcifs.smb.SmbFile.resolveDfs(SmbFile.java:671) was spawning numerous Threads that were consuming all of the RAM availble to naitive thread in my JVM. Increasing the amount of RAM to the JVM didn’t help.
The solution that I found was to set the following properties in my application prior to the instantiation of any of the jcifs.* classes. In this case, these properties were set in the main method of my entry point class.
System.setProperty(“jcifs.resolveOrder”, “DNS”);
System.setProperty(“jcifs.smb.client.dfs.disabled”, “true”);
Once set, I was able to run as expected without the OutOfMemoryErrors