#16 JVM Crash

open
nobody
None
5
2014-09-30
2014-01-10
NAAL
No

Hi,
In our multithread tool, we are using the 7zjbind to extract 7z archives. Our tool extracts several archives in parallel (one thread per 7z archive).
Every once in a while the JVM crashes in a call to EndCPPToJava native code:

A fatal error has been detected by the Java Runtime Environment:

SIGSEGV (0xb) at pc=0x00002aaad6c125af, pid=1927, tid=1215662400

JRE version: Java(TM) SE Runtime Environment (7.0_40-b43) (build 1.7.0_40-b43)
Java VM: Java HotSpot(TM) 64-Bit Server VM (24.0-b56 mixed mode linux-amd64 compressed oops)
Problematic frame:
C [lib7-Zip-JBinding.so+0x875af] NativeMethodContext::EndCPPToJava()+0xcf

Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again

An error report file with more information is saved as:
hs_err_pid1927.log

If you would like to submit a bug report, please visit:
http://bugreport.sun.com/bugreport/crash.jsp
The crash happened outside the Java Virtual Machine in native code.
See problematic frame for where to report the bug.

WE are using java’s fork/join: forkJoinPool = new ForkJoinPool(numberOfCoresToUse);
numberOfCoresToUse is limited to 75% of number of cores.
Callable#call()Implementation is simple and straight forward, since in our system the same 7z archive can be extracted to multiple locations, we make sure that we extract only if the archive not already is being extracted:

/*
* {@inheritDoc}
* @see java.util.concurrent.Callable#call()

/
@Override
public ActionResult call() throws Exception {

….

/*
* Same archive can be extracted to different locations,
* in that case the OS might lock the file and RandomAccessFile
* creation might fail, hence wait for the archive file to be
* extracted before continuing.

/
synchronized (ARCHIVE_BEING_EXTRACTED) {
while(ARCHIVE_BEING_EXTRACTED.contains(archiveLocation)) {
MY_LOGGER.trace(Thread.currentThread().getName()+ ", waiting to extract: "+archiveLocation);
ARCHIVE_BEING_EXTRACTED.wait(10000);
}
ARCHIVE_BEING_EXTRACTED.add(archiveLocation);
}
extract(archiveLocation, passwd, destDir);

private ActionResult extract(File archiveLocation,
String password,
File destDir) throws SevenZipException {
// ForkJoinPool f = new ForkJoinPool(2);
RandomAccessFile randomAccessFile=null;
try {
randomAccessFile = new RandomAccessFile(archiveLocation, "r");
} catch (FileNotFoundException e) {
// the caller has made sure that there will be archives...
String errorMsg = e.getMessage()+ ", archive: "+archiveLocation;
MY_LOGGER.error(errorMsg);
MY_LOGGER.debug(errorMsg,e);
return new ActionResult(false, errorMsg, e);
}
ISevenZipInArchive inArchive = SevenZip.openInArchive(null, // autodetect archive type
new RandomAccessFileInStream(randomAccessFile),password);

ExtractAll extractAll = new ExtractAll(password, destDir.getAbsolutePath(),inArchive.getSimpleInterface());
long start = System.currentTimeMillis();
inArchive.extract(null, false, extractAll);

….

ExtractAll:

/
* @return
* @throws SevenZipException
*/
@Override
public String cryptoGetTextPassword() throws SevenZipException {
return passwd;
}
/

* @param total
* @throws SevenZipException
*/
@Override
public void setTotal(long total) throws SevenZipException {
this.total=total;
}

/** 
 * {@inheritDoc}
 * @see net.sf.sevenzipjbinding.IProgress#setCompleted(long)
 */
@Override
public void setCompleted(long completeValue) throws SevenZipException {
  MY_LOGGER.trace(output+", completed: " +completeValue+", total: "+total);
}

/** 
 * {@inheritDoc}
 * @see net.sf.sevenzipjbinding.IArchiveExtractCallback#getStream(int, net.sf.sevenzipjbinding.ExtractAskMode)
 */
@Override
public ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException {
  if(cancel) {
    return null;
  }
  if(extractAskMode == ExtractAskMode.EXTRACT) {
    ISimpleInArchiveItem item = inArchive.getArchiveItem(index);

    if(item.isFolder()) {
      return null;
    }

    String filePath = item.getPath();

    //for zero length files, 
    //just create the file and set permissions
    if(item.getSize()==0) {
      File aFile=new File(output,filePath);
      aFile.getParentFile().mkdirs();
      try {
        aFile.createNewFile();
        setPemissions(aFile.getAbsolutePath(), item.getAttributes());
      } catch (IOException e) {
        MY_LOGGER.debug("Could not create zero length file:" +aFile,e);
      }
      return null;
    }
    String errorMessage=null;
    //      //                                         item.getSize(), 
    //      //                                         item.getPackedSize(), 
    //      //                                         item.getPath()));
    synchronized (writerLock) {
      try {
        SevenZWriter sevenZWriter = idToSevenZWriter.get(new Integer(index));
        if(sevenZWriter==null) {
          sevenZWriter = new SevenZWriter(output+File.separator+filePath, item.getAttributes());
          idToSevenZWriter.put(new Integer(index), sevenZWriter);
          sevenZWriter.setSize(item.getSize());
        }
        return sevenZWriter;
      } catch (Throwable e) {
        errorMessage = e.getMessage()+ ", filePath: "+filePath;
        MY_LOGGER.error(errorMessage);
        MY_LOGGER.debug(errorMessage, e);
      }
    }

SevenZWriter:
/*
* {@inheritDoc}
* @see net.sf.sevenzipjbinding.ISequentialOutStream#write(byte[])

/
@Override
public int write(byte[] data) throws SevenZipException {
if(!cancel) {
try {
out.write(data);
out.flush();
} catch (IOException e) {
throw new SevenZipException(e.getMessage(),e);
}
wrote+=data.length;
MY_LOGGER.trace(file+ "total size: "+size+" remaining: "+ (size-wrote));
if((size-wrote)==0) {
MY_LOGGER.trace(file+ " DONE!");
close();
if(isSoftLink(attribute)) {
doSymlink(file+".s_l_n_k_TMP",file);
}
setPemissions(file, attribute);

      synchronized(LOCK) {
        totalSizeOfExtractedFiles+=wrote;
        totalNumOfFilesExtracted++;
        if((totalNumOfFilesExtracted %NUM_OF_FILES_BEFORE_UPDATE_PROGRESS_BAR == 0) || totalNumOfFilesExtracted>=TOTAL_NUM_OF_FILES_TO_EXTRACT) {
          updateProgress();
        }
      }
    }
    return data.length;
  } else {
    throw new SevenZipException("Canceled");
  }
}
/**
 * close the output file.
 */
public void close() {
  try {
    out.flush();
  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }
  try {
    out.close();
  } catch (IOException e) {
    MY_LOGGER.debug("GOT IOException while closing output file",e);
  }
}

Have you seen this crash before?
We would highly appreciate your help, and would be more than happy to help you out trying to debug this, just let us know.
Thanks,
/N

Discussion

  • Boris Brodski
    Boris Brodski
    2014-01-10

    Dear N,

    thank you for reporting this bug and offering help to debug it! I appreciate it a lot.

    I will look into it and get back to you.

    Kind regards,
    Boris Brodski