私はsun.misc.Unsafeの文書を理解するのに苦労しています - それは一般的な使用を意図していないと私は推測するが、誰も実際にそれが読みやすくて気にしないです - しかし、私は実際には本当にのアドレスを見つける方法が必要です配列の要素(ネイティブコードにポインタを渡すことができるように)。誰もこれを行う作業コードを持っていますか?それは信頼できますか?ここでsun.misc.Unsafeを使用してJava配列項目のアドレスを取得しますか?
答えて
配列を使用する代わりに、ByteBuffer.allocateDirect()ダイレクトバッファを使用できます。これはフィールド内のアドレスを持ち、このアドレスはByteBufferの寿命の間は変化しません。直接のByteBufferは最小限のヒープスペースを使用します。リフレクションを使用してアドレスを取得できます。
Unsafeを使用してアドレスを取得することはできますが、問題はGCがいつでも移動できることです。オブジェクトはメモリに固定されていません。
あなたがこの問題(およびその他)を避けるために、Javaオブジェクトから/にデータをコピーするために特別なメソッドを使用することができますJNIで私はあなたのCコードとオブジェクトの間でデータを交換したい場合は、これらを使用することをお勧め。
バイト配列の観点から定義されている既存のAPIを実装しようとしているので、直接バイトバッファ(むしろ問題を簡単に解決できるようになります)を使用するのではなく、コピーのペナルティを避けようとしていますバッファの余分なセットから。これは最後の手段としては十分ですが、よりよい方法が必要です。 JNIを使用すると、これは簡単になりますが、残念ながら私はJNAを使用しています.JNAは、配列全体を処理するために必要なインタフェースを備えていないようです。 – Jules
@Jules、JNIはGCを傷つける可能性のある 'GetPrimitiveArrayCritical'を付けたい場合を除き、それ自身でコピーを生成します。弾丸を噛んで、直接(バッファ)メモリにコピーします。これが唯一実現可能な解決策です。例えば、インプラント。 FileOutputStream(SocketOutputStream extends)は、スタック上の要素のコピーを使用します。コピーのペナルティはそれほど高くはありません。なぜなら、いずれかの方法で支払う必要があるデータ(およびキャッシュミス)の負担コストが最も高いからです。コピーするとキャッシュラインもプリフェッチされるので、ネイティブコードがどのように機能しているかをさらによく見極めることができます。 – bestsss
@Jules、サイドノート:javax.net.ssl.SSLEngineでさえバッファの使用が許可され、すべてのアルゴリズムがbyte []であり、ダイレクトバッファを一時配列にコピーすることになります。これは逆の話であり、その道徳ですSSLEngineを使用しない直接バッファを使用しないでください。 – bestsss
は、作業サンプルです。しかし、あなたは、Unsafe
クラスの不適切な使い方であなたのJVMを簡単にクラッシュさせるかもしれないので注意してください。
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class UnsafeTest {
public static void main(String... args) {
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
int ten = 10;
byte size = 1;
long mem = unsafe.allocateMemory(size);
unsafe.putAddress(mem, ten);
long readValue = unsafe.getAddress(mem);
System.out.println("Val: " + readValue);
}
}
そのコードは、DirectByteBufferの動作とまったく同じように完全に安全でなければなりません。残念ながら、既存の配列のデータにアクセスすることはできません。 – Jules
@StephenC、コードはまったく問題ありません。基本的には 'char * mem = malloc(size); ... 'です。これはGCには決して触れません。 – bestsss
コードは問題ありませんが、割り当てられたメモリを解放することも検討する必要があります。 DirectByteBufferを参照してください。また、割り当てられたメモリがゼロにならないので、ダイレクト・アレイがゼロで初期化されていると仮定することはできません。 –
- 1. foreachループから各配列項目をテーブルデータとして取得
- 2. javascriptで配列の項目を取得
- 3. push jsonはリクエスト項目を配列に取得します
- 4. JSONのすべての項目を取得して配列に入れます
- 5. mybatisを使用してPOJO項目の配列をストアドプロシージャに渡しますか?
- 6. ループを使用してListViewの各項目を取得しますか?
- 7. 選択したコンボボックス項目から配列情報を取得します。
- 8. 次の配列のすべての項目を取得する
- 9. 配列から項目を取得できませんか? [AHK]
- 10. Java WebServiceを使用してIPアドレスから国コードを取得
- 11. TFS- java sdkを使用して作業項目データを取得する方法
- 12. 配列内の各項目のIDを取得し、オプション値の各項目に追加します
- 13. 異なる確率で配列のランダムな項目を取得しますか?
- 14. linqを使用してDistinct項目を取得する方法
- 15. 変数名として配列項目を使用する
- 16. ContextMenuを使用してListBoxの選択項目を取得
- 17. 配列から一意の項目を取得する
- 18. Java 1.5を使用してWindowsでイーサネットアダプタのIPv4アドレスを取得
- 19. 配列をループして項目のインデックスを取得する - 即時
- 20. reduceを使用して配列項目を変更します。悪いパターン?
- 21. PHPはループのない多次元配列から項目の配列を取得しますか?
- 22. 配列をループし、配列項目
- 23. boolがfalseの配列の最初の項目を取得します
- 24. ObjectmapperはJSON内の1つの項目の配列を取得します
- 25. javaを使用してmongodb配列要素を取得します。
- 26. 配列から項目数xを取得する
- 27. Angularjsを使用して配列の各項目を数えます
- 28. Firebaseスナップショットから項目の配列を取得
- 29. 配列のforeachループとifステートメントを使用して配列の最初の項目を返します
- 30. キー配列として列のいずれかを使用して、データベースから配列を取得します
http://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafe –
[なぜ開発者はプログラムを書くべきでないのですか?] 「Sun 'Packages」(http://www.oracle.com) .com/technetwork/java/faq-sun-packages-142232.html) – BalusC
imo、unsafe docは大丈夫ですが、とにかく一般向けではありません。いくつかのガイドラインが必要な場合は、java.util.concurrentおよびjava.util.concurrent.atomicの読み込みを開始してください。unsafeはC(またはアセンブラ)とかなり近いです。経験がなければ、安全でないことはあなたのためではありません。 Javaコードの逆アセンブルし取得する方法:あなたは(つまり、それについてのSOに質問をしていないものを知っていればhttp://wikis.sun.com/display/HotSpotInternals/PrintAssembly – bestsss