これは、Oracle または OpenJDK JRE で Java 1.7 を使用している場合にのみ発生するようです。Java 1.6 (Oracle と OpenJDK の両方) を使用すると、すべてが機能します。
少し前に、Linux で JNI 共有ライブラリ (Java ムービー プレーヤーに使用される LibVLC のラッパー) をコンパイルしようとしました。_IO_file_underflow
ただし、特定のネイティブ関数を呼び出すと、散発的かつ任意の瞬間に JVM がクラッシュし、エラー ログには libc.soの関数が問題のあるフレームとして示されていました。
最終的に、コンパイル中にいくつかの GCC フラグが欠落しているだけであることがわかりました。問題はおそらく特定の最適化が原因であるか、JVM が予期していなかったものでした。このガイドとこの質問への回答に従った後、コンパイル コマンドに や などのフラグを追加すると、すべてが完全に機能しまし-fno-strict-aliasing
た。 -pthread
少なくとも、これは OpenJDK 1.6 を使用する OpenSuSe 12.1 で機能しました。残念ながら、OpenSuse 12.2 と OpenJDK 1.7 にアップグレードした後、アプリケーションが再びクラッシュし始め、おなじみの次のエラー メッセージが表示されました。
#
[thread -1984603328 also had an error]# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0xb770ff38, pid=19354, tid=2309835584
#
# JRE version: 7.0_09-b30
# Java VM: OpenJDK Client VM (23.2-b09 mixed mode linux-x86 )
# Problematic frame:
# C [libc.so.6+0x127f38] _IO_file_underflow+0x68
#
# 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:
# /usr/fids/build_vlcplayer/hs_err_pid19354.log
#
# If you would like to submit a bug report, please include
# instructions on how to reproduce the bug and visit:
# http://icedtea.classpath.org/bugzilla
#
次のコマンドを使用してコンパイルしています (フラグの多くはおそらく冗長です)。
gcc -I/usr/lib/jvm/java-1.7.0-openjdk-1.7.0/include/ -I/usr/lib/jvm/java-1.7.0-openjdk-1.7.0/include/linux/ -fno-strict-aliasing -fno-omit-frame-pointer -fPIC -pthread -static-libgcc -D_REENTRANT -Di586 -DARCH='"I586"' -DLINUX -D_LARGEFILE64_SOURCE -D_GNU_SOURCE -D_LITTLE_ENDIAN -Wall -Wno-unused-parameter -DDEBUG_MODE -shared -lvlc -lc -lX11 movieplayer.c -Wl,-soname,movieplayer.so -o movieplayer.so
GCC バージョン 3.3 とバージョン 4.7 の両方でこれを試しました。
同じコードが Windows (Oracle JDK 1.6 または 1.7 を使用) または OpenSuSe 12.1 (OpenJDK 1.6 を使用) で正常に動作するため、movieplayer.c の実際のソース コードは関係ないと思います。それにもかかわらず、クラッシュが発生する部分は次のとおりです。
/** The LibVLC instance.*/
static libvlc_instance_t * vlcInstance = NULL;
/** The media object representing the video. */
static libvlc_media_t * media = NULL;
/** The media player. */
static libvlc_media_player_t * mediaPlayer = NULL;
...
const char * fname = str + 1;
DEBUGMSG("Opening file: '%s'\n", fname);
// Create a VLC media object for this file.
media = libvlc_media_new_path (vlcInstance, fname);
if(media)
{
// Parse the media. This allows fetching duration and track info.
DEBUGMSG("Parsing media.");
libvlc_media_parse(media); // <-- Crash occurs at this point.
// Create the media player.
DEBUGMSG("Creating a media player.");
mediaPlayer = libvlc_media_player_new_from_media(media);
...
}
...
このコードを変更すると、他の LibVLC 関数を呼び出すとき、またはあるケースでは POSIXsleep
関数を呼び出すときに、同じクラッシュがさまざまな時点で発生します。
基本的に私の質問は次のとおりです。アプリケーションを正しくコンパイルしていないためにこれらのクラッシュが発生したと考えるのは正しいですか? もしそうなら、私は何を間違っていますか?