問題タブ [java-native-interface]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - JavaからWindowsカーネル関数を呼び出す最も簡単な方法は何ですか?
これを行う方法を探しているときに、JNIとJNAのようなさまざまなオプションについて漠然とした議論を見つけましたが、具体的な例についてはあまり説明していません。
コンテキスト:JavaFile.renameTo()
がその仕事を実行できない場合(何らかの理由で、少し問題があります)、kernel32.dllで定義されているこのネイティブWindows関数を直接使用することにフォールバックしたいと思います(この回答から):
では、どのようなアプローチを使用しても、Javaコード内からその関数をどの程度正確に呼び出すでしょうか。私は、Java以外のコードや追加の手順(コンパイルやデプロイメントなど)を最小限に抑えた、最も簡単な方法を探しています。
java - Mavenを使用したDLL依存関係の管理
Mavenが依存関係を管理しているJavaプログラムがあります。それらの依存関係の1つは、別のプログラムのJNIラッパーです。Mavenは関連するJARファイルへの参照を処理しますが、私はDLLファイルを自分でいじりまわしているままです。
MavenにDLLも処理させる良い方法はありますか?理想的には、JARファイルのようにDLLをローカルリポジトリにロードしたいと思います。
java - Linuxでjavasystem.loadlibraryエラーをデバッグする方法は?
Linuxで実行しようとしているJNIを介してCコードを呼び出すJavaプログラムがあります。外部コードは、2つの.soファイルで構成されています。1つはJNIバインディング(swigで構築)用で、もう1つは実際の関数用です。同じディレクトリに2つのライブラリがあり、LD_LIBRARY_PATHが正しく設定されています。lddはコマンドラインから実行しても問題を報告しませんが、Eclipseエディターの[構成の実行]ダイアログでLD_LIBRARY_PATHを同じ値に設定してプログラムを実行しようとすると、次のエラーが発生します。
java.lang.UnsatisfiedLinkError:[ライブラリへのパス] /[JNIバインディングライブラリ].so:[実際のコードライブラリ] .so:共有オブジェクトファイルを開くことができません:そのようなファイルまたはディレクトリはありません
これにより、JNIラッパーライブラリが正常にロードされたと思いますが、そのライブラリが実際のコードを含むライブラリをロードしようとすると失敗します。これをさらにデバッグする方法はありますか?
さらに、この問題はeclipseエディター自体で発生しており、コードをjarにパッケージ化して、独立したjvmインスタンス内で実行しようとしたことはありません。
java - registerNatives() メソッドは何をしますか?
Javaでは、Objectクラスのprivate staticメソッドregisterNatives()
は何をしますか?
java - Java に C++ デストラクタ (JNI) を強制的に呼び出す
この質問は以前にもあったと思いましたが、ここでは見つかりませんでした...
SWIG を使用して C++ クラスの JNI ラッパーを作成しました。Java がクラスの finalize() を呼び出すことがないように見えることを除いて、すべてがうまく機能するため、クラスのデストラクタが呼び出されることはありません。クラスのデストラクタは最終的なファイル I/O を実行するため、残念ながら、これは単なるマイナー メモリ リークではありません。
Google で検索すると、Java を強制的に GC にしてオブジェクトを破棄する方法はないようです。真実?
SWIG ファイルを操作して C++ デストラクタを呼び出す Java 関数を作成できることはわかっていますが、このクラスは複数の異なるプラットフォーム/言語のエンド ユーザーによって使用されているため、Java のみのクラスを追加すると、私たちの技術に矛盾が生じます。作家は気に入らないでしょう。
java - Java String から byte[] への変換のパフォーマンスを向上させる方法について何か提案はありますか?
String -> byte[] 変換を集中的に使用するコードを継承し、その逆も同様です。基本的に、Java オブジェクトは、その構成部分を文字列に変換する方法を知っており、文字列はバイト [] に変換されます。次に、このバイト配列は、JNI を介して C++ コードに渡されます。C++ コードは、byte[] を C++ std::strings に再構成し、それらを使用して、Java オブジェクトをミラーリングする C++ オブジェクトをブートストラップします。もう少し続きがありますが、これはこのコードがどのように機能するかの概要です。通信は双方向でこのように機能するため、C++ -> Java 遷移は、前述の Java -> C++ 遷移のミラー イメージです。
このコードの一部 (String から byte[] への実際の変換) が、予期せずプロファイラーに表示され、大量の CPU を消費しています。確かに、大量のデータが転送されていますが、これは予想外のボトルネックです。
コードの基本的な概要は次のとおりです。
機能にはもう少しありますが、それほど多くはありません。上記の関数は、文字列/文字列化されたオブジェクトごとに 1 回呼び出され、すべての構成要素が ByteArrayOutputStream に書き込まれた後、ByteArrayOutputStream は byte[] に変換されます。呼び出しを抽出して上記をよりプロファイラーに適したバージョンに分解するとconvert_me.getBytes()
、この関数の時間の 90% 以上が getBytes() 呼び出しに費やされていることがわかります。
getBytes() 呼び出しのパフォーマンスを改善する方法はありますか、または同じ変換を達成するための別の潜在的に高速な方法はありますか?
変換されるオブジェクトの数は非常に多くなります。本番データの小さなサブセットのみを使用しているプロファイリングの実行では、1,000 万以上の上記の変換関数の呼び出しが見られます。
プロジェクトの本番環境へのリリースが近づいているため、現時点では実行できないいくつかの回避策があります。
- シリアライゼーション インターフェイスを書き直して、JNI レイヤー全体で String オブジェクトを渡すだけにします。これは (私にとって) 状況を改善する明白な方法ですが、シリアライゼーション レイヤーの大幅な再設計が必要になります。今週初めに UAT に移行するという事実を考えると、この種の複雑な変更を行うには遅すぎます。これは次のリリースに向けた私の最優先事項なので、完了します。ただし、それまでは回避策が必要ですが、これまでのところコードは機能しており、何年も使用されており、ほとんどの問題は解決しています。まぁ、演出は別として。
- JVM (現在は 1.5) を変更することもできません。残念ながら、これはクライアントのマシンにインストールされているデフォルトの JVM であり、1.6 への更新 (この場合は高速である場合とそうでない場合があります) は残念ながら不可能です。大規模な組織で働いたことのある人なら、おそらくその理由を理解しているでしょう...
- これに加えて、すでにメモリの制約に直面しているため、少なくともより大きな文字列とそのバイト配列表現をキャッシュしようとすると、洗練されたソリューションになる可能性がありますが、解決するよりも多くの問題が発生する可能性があります。
java - java、System.loadlibrary("someDLLFile") で unstatisfied リンク エラーが発生する
いくつかの JNI フックを C++ ライブラリに書き込み、Java サーバー プロジェクト用にいくつかの DLL ファイルを作成しました。DLL ファイルと jar ファイルが「C:/server」の下の同じフォルダーにあるとします。
以下を使用してこれらの DLL ファイルにアクセスしています。
C++ コードを必要とするクラスで。
私が直面している問題は、このサーバーを自分のマシンで実行すると、「サーバー」フォルダーの場所に関係なく、すべてが正常に機能することです。しかし、同僚にテストしてもらうと、次のような結果が得られます。
DLL ファイルを jar ファイルと同じフォルダーに配置したいのですが、誰かに PATH 変数を構成させたくないのです。
System.loadLibrary() がフォルダーの場所に関係なく自分のマシンでは機能するのに、別のコンピューターでは機能しないのはなぜですか?
web-applications - .dll が別のクラスローダーに既にロードされていますか?
レガシ C++ コードのデータとメソッドにアクセスするために JNI 呼び出しを行う必要がある Tomcat 3.2.1 で実行されている webapp があります。Web アプリケーションの起動時にサーブレットがロードされ、そのinit
メソッドの一部として、その Web アプリケーション インスタンスに固有のデータ セットが C++ データ構造にロードされます。
このサーブレットの Java コードには、次のものが含まれています。
webapp が 1 つしかない場合は問題なく動作します (「webapps/aaa」と呼びましょう)。
C++ データ構造で使用されるデータ セットを除いて webapps/aaa と同一の 2 番目の webapp (「webapps/bbb」) がある場合、webapps/aaa は問題なく起動しますが、webapps/bbb が起動すると、次のようなエラー:
各インスタンスには特定の Web アプリに固有のデータを含める必要があるため、Web アプリごとにネイティブ ライブラリの個別のインスタンスが必要です。私はメールアーカイブを検索し、Craig McLanahan によるクラスローダーの階層を説明する電子メールを読みました。しかし、各 webapp のネイティブ ライブラリの一意のインスタンスを読み込むことに固有のものを見つけることができませんでした。
jsp - JNIを使用したJava Bean?
Java Bean コードにネイティブ メソッドを追加しました。
次に、System32 フォルダーに .dll ファイルをコピーしました。
JSPでjavabeanを使用している間。
エラーが発生します:
HTTP ステータス 500 -
タイプ例外レポート
メッセージ
サーバーで内部エラー () が発生したため、この要求を実行できませんでした。
例外
根本的な原因
根本的な原因
note 根本原因の完全なスタック トレースは、Apache Tomcat/6.0.20 ログで入手できます。アパッチ トムキャット/6.0.20
Java Bean コード: