Java ZipInputStream breaks in a thread, but not in main thread - java

I'm unable to wrap my head around this. The following code works perfectly:
public static void main(String[] args) {
//new Thread(() -> {
try {
Path zipFile = Paths.get("C:\\path\\to\\zipfile.zip");
Path outDir = Files.createDirectories(Paths.get("C:\\path\\to\\outDir"));
try (ZipInputStream inputStream = new ZipInputStream(Files.newInputStream(zipFile))) {
ZipEntry entry;
while ((entry = inputStream.getNextEntry()) != null) {
Path outPath = outDir.resolve(entry.getName());
if (entry.isDirectory()) {
if (!Files.exists(outPath)) {
Files.createDirectory(outPath);
}
} else {
try (OutputStream outputStream = Files.newOutputStream(outPath)) {
inputStream.transferTo(outputStream);
}
}
System.out.println(entry.getName());
}
}
} catch (IOException e) {
e.printStackTrace();
}
//}).start();
}
However, uncommenting the thread code causes the program to hang at the exact same file every time:
public static void main(String[] args) {
new Thread(() -> {
try {
Path zipFile = Paths.get("C:\\path\\to\\zipfile.zip");
Path outDir = Files.createDirectories(Paths.get("C:\\path\\to\\outDir"));
try (ZipInputStream inputStream = new ZipInputStream(Files.newInputStream(zipFile))) {
ZipEntry entry;
while ((entry = inputStream.getNextEntry()) != null) {
Path outPath = outDir.resolve(entry.getName());
if (entry.isDirectory()) {
if (!Files.exists(outPath)) {
Files.createDirectory(outPath);
}
} else {
try (OutputStream outputStream = Files.newOutputStream(outPath)) {
inputStream.transferTo(outputStream);
}
}
System.out.println(entry.getName());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
If I try to debug the program, it works fine, only when running in non-debug mode, within a thread does this occur. Furthermore, the zip extracts without issue using Windows Explorer and 7-Zip. I'm approaching hair-pull-out levels on this, any help is greatly appreciated.
For reference, the zip file I'm using for testing (I'm working on a mod launcher for 7 Days to Die) can be found here: https://github.com/KhaineGB/DarknessFallsBBM45/archive/refs/heads/master.zip

Related

How to prevent the block from being displayed, finally, if there is no path to the file

Problem: if the path to the file was not specified in the arguments, then it still displays the phrase "The file was closed". This works 2 times. In uploadToFile and read method. I pass one path in the arguments, and the second is written in the DownloadFile
public class Task implements AutoCloseable {
public static void main(String[] args) throws IOException {
String DownloadFile = "C:\\Users\\VGilenko\\IdeaProjects\\Task\\src\\main\\resources\\Out.txt";
Map<String, Departament> departments = new HashMap<>();
String path = args.length > 0 ? args[0] : null;
read(path, departments);
transferToDepartment(departments, DownloadFile);
}
private static void uploadToFile(List download, String path) {
int i = 0;
try (FileWriter writer = new FileWriter(path, false)) {
...
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
} finally {
System.out.println("The file was closed");
}
}
public static void transferToDepartment(Map<String, Departament> departments, String downloadFile) {
List<String> download = new ArrayList<>();
...
}
uploadToFile(download, downloadFile);
}
public static void read(String path, Map<String, Departament> departments) throws IOException {
assert path != null;
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "CP1251")); br) {
.....
}
}
} catch (FileNotFoundException e) {
System.out.println("The file was not found, check the path");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Correct the file path, step out of the array");
} catch (NullPointerException e) {
System.out.println("You forgot to register the path to the file");
} finally {
System.out.println("The file was closed");
}
}
#Override
public void close() {
System.out.println("The file was closed");
}
}
You have your printout "The file was closed" in your finally statement. If you don't specify a file, you will catch an Exception, and your finally block will be executed.
An easy fix would be to check for the existence of the path (not being empty, not being null).

Java File.deleteOnExit() not working Windows 10

I'm trying to write code for a jarfile which if executed, it shutdowns the JVM and then deletes the jarfile. This is what I've tried to do so far but it is not deleting the file after the JVM closes.
public static void check() {
if (isJarFile()) {
try (Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())) {
String remote_hash = s.nextLine().trim();
File jarFile = getJarFile();
if (jarFile != null && !remote_hash.equals(getMD5Checksum(jarFile.getAbsolutePath()))) {
jarFile.setWritable(true);
jarFile.deleteOnExit();
}
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}
public static byte[] createChecksum(String filename) throws Exception {
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}
public static String getMD5Checksum(String filename) throws Exception {
byte[] b = createChecksum(filename);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
public static File getJarFile() {
try {
return new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
Can someone explain why deleteOnExit is not working in this instance?
Make sure that you close any stream that you have open on a file before exiting your JVM. Otherwise, the shut down hook that is supposed to delete the file cannot trigger on Windows as opening the stream triggers a file lock on the OS-level.
For your example, it means that you must not end the JVM process before exiting the try-with-ressources-block which is roughly translated into:
Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())
try {
// your code
System.exit(0);
} finally {
s.close(); // Never executed
}
As your program exits before the finally block is executed, the shut down hook is triggered without closing the stream and the file cannot be deleted.
Note that the following code will work for your purposes as the finally block is executed after closing the try-with-ressources argument:
try (Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())) {
// your code
} catch (Exception e) {
e.printStackTrace();
} finally {
System.exit(0);
}

Hadoop YARN Map Task running out of physical and virtual memory

I have the following method that I run from my map task in a multithreaded execution , however this works fine in a standalone mod e, but when I runt this in Hadoop YARN it runs out of the physical memory of 1GB and the virtual memory also shoots up.
I need to know if I am doing anything wrong from a programming perspective, I think I am closing all the streams that I am opening ASAP , so I see no reason for a memory leak to happen . Please advise.
Thanks.
public static void manageTheCurrentURL(String url) {
logger.trace("Entering the method manageTheCurrentURL ");
InputStream stream = null;
InputStream is = null;
ByteArrayOutputStream out = null;
WebDriver driver = null;
try {
if (StringUtils.isNotBlank(url)) {
caps.setJavascriptEnabled(true); // not really needed: JS
// enabled by default
caps.setCapability(
PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
"/usr/local/bin/phantomjs");
// Launch driver (will take care and ownership of the phantomjs
// process)
driver = new PhantomJSDriver(caps);
driver.get(url);
String htmlContent = driver.getPageSource();
if (htmlContent != null) {
is = new ByteArrayInputStream(htmlContent.getBytes());
ByteArrayDocumentSource byteArrayDocumentSource = new ByteArrayDocumentSource(
is, url, "text/html");
Any23 runner = new Any23();
runner.setHTTPUserAgent("test-user-agent");
out = new ByteArrayOutputStream();
TripleHandler handler = new NTriplesWriter(out);
try {
runner.extract(byteArrayDocumentSource, handler);
} catch (ExtractionException e) {
} finally {
if (driver != null) {
driver.quit();
//driver.close();
}
try {
handler.close();
} catch (TripleHandlerException e) {
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
if (out != null) {
stream = new ByteArrayInputStream(out.toByteArray());
Iterator<Node[]> it = new DeltaParser(stream);
if (it != null) {
SolrCallbackForNXParser callback = new SolrCallbackForNXParser(
url);
callback.startStory();
while (it.hasNext()) {
Node[] abc = it.next();
callback.processStory(abc);
}
callback.endStory();
}
}
}
}
} catch (IOException e) {
return;
}
finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
}
}
}
logger.trace("Exiting the method manageTheCurrentURL ");
}

How to continue program execution after an Exception is caught in Java

My program loops through some folders and copies the files in the folder to a new file with a new name. Some files will copy and others will get a Java Exception saying access denied. When that happens the program terminates. I want it to skip and not copy that file and just keep going. Here is the copy function.
private static void copyFile(File source, File dest)
throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
} catch (Exception e){
}
finally{
inputChannel.close();
outputChannel.close();
}
}
Any help would be great. Thanks!
Just catch the exception in the calling program to your copyFile method and continue on. The reason I removed the catch block in the copyFile method is it allows the copyFile method to be generally used (times when you might want to stop processing during an exception and times when you want to ignore the exception).
...
for (File source : sources) {
try {
copyFile(source, dest);
}
catch (Exception ignore) {
// ignore exception and continue
}
// do your other stuff here
}
private static void copyFile(File source, File dest)
throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
}
finally{
if (inputChannel != null) inputChannel.close();
if (outputChannel != null) outputChannel.close();
}
}
In your catch block, you can use a continue statement to "skip" the file currently being processed.
Something like below (also incorporates Prabhakaran's suggestion of null checking values):
private static void copyFile(File source, File dest)
throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
} catch (Exception e) {
// You should be logging any exception here. Empty blocks == bad practice.
continue;
} finally {
if(inputChannel != null {
inputChannel.close();
}
if(outputChannel != null {
outputChannel.close();
}
}
}
change
finally{
inputChannel.close();
outputChannel.close();
}
to
finally{
try {
if(inputChannel!=null)
inputChannel.close();
if(outputChannel!=null)
outputChannel.close();
} catch (Exception e){
}
}
and remove the throws IOException from copyFile(File source, File dest) method
now your method look like this
private static void copyFile(File source, File dest){
}

Java continue executing loop if exception was throwd

Example: say I want to open a file. If I get a FileNotFoundException, I need to wait for some time and try again. How can I gracefully do that? Or do I need to use nested try/catch blocks?
Example :
public void openFile() {
File file = null;
try {
file = new <....>
} catch(FileNotFoundException e) {
}
return file;
}
You could use a do { ... } while (file == null) construct.
File file = null;
do {
try {
file = new <....>
} catch(FileNotFoundException e) {
// Wait for some time.
}
} while (file == null);
return file;
public File openFile() {
File file = null;
while (file == null) {
try {
file = new <....>
} catch(FileNotFoundException e) {
// Thread.sleep(waitingTime) or what you want to do
}
}
return file;
}
Note that this is a somewhat dangerous method, since there is no way to break out unless the file eventually appears. You could add a counter and give up after a certain number of tries, eg:
while (file == null) {
...
if (tries++ > MAX_TRIES) {
break;
}
}
public File openFile() {
File file = null;
while(true){
try {
file = new <....>
} catch(FileNotFoundException e) {
//wait for sometime
}
if(file!=null){
break;
}
}
return file;
}

Categories

Resources