6

ScriptEngineオブジェクトのバインディングのセット全体をどうにかしてディープ クローンする必要があります。

私が試したこと

  • これまでにCloner ライブラリを使用して Bindings 構造全体を複製しようとしました。プライベート変数を含む正確なコピーが保証されるため、これが機能する場合は素晴らしいでしょう。しかし、これは jvm ヒープの破損につながります (jvm は終了コード -1073740940 でクラッシュするだけです)。クラッシュしないこともありますが、本来のSystem.out.println()動作が停止するなど、奇妙なことが起こります...

  • また、ScriptEngine 内で js コードを使用してオブジェクトのクローンを作成することも検討しました。これにより、それらを NativeObjects として取得し、いくつかの Java マップで管理できます。しかし、私が見つけたすべてのクローン作成方法には欠陥があります。オブジェクトの正確なスナップショットが必要です。たとえば、2 つのオブジェクト a と b のそれぞれに同じオブジェクト c を参照するフィールド (a.fa と b.fb など) が含まれている場合、jQuery.extend()(たとえば) フィールドa.faを使用しb.fbてクローンを作成すると、クローンされた a と b の異なるクローンが参照されます。 c、1 つの同じクローンを参照する代わりに。そして、他の多くのエッジの問題。

  • また、(バインディングだけでなく) Cloner を使用して ScriptEngine 全体のクローンを作成しようとしました。また、(バンドルされた ScriptEngine ラッパーの代わりに) Rhino の js エンジンを使用してスコープ全体のクローンを作成しようとしました。しかし、ヒープの破損の問題は解決しません。

なぜ私はそれをする必要があるのですか

これが必要なのは、ScriptEngine バインディング全体の値を以前のポイントに復元できる必要があるためです。バインディングの正確なスナップショットを作成する必要があります。

このアプリケーションは、js コードが添付されたノード (Java で実装) を使用してステート マシンを実行することで構成される、私の博士研究プロジェクトの一部です。js コードはエンド ユーザーによって入力され、実行時に評価されます。パスを介して最終状態に到達できない場合、アルゴリズムは逆方向に進み、別のパスを見つけようとします。戻るたびに、js エンジンのバインドで発生した可能性のある変更を元に戻す必要があります。


すべてのグローバル変数名は js 評価の前に認識され、オブジェクトです (ユーザーがノードのコードに入力すると、これは (Java 内で) 特定の名前パターンを持つ js オブジェクトに編成されます)。ただし、ユーザーの js コードによって制御されるため、コンテンツは何でもかまいません。

したがって、私の唯一の解決策は、js コードを使用して js オブジェクトを複製することだと思います。

4

2 に答える 2

2

別のアプローチを提案できますか。

  • ScriptEngine を複製しようとしないでください。Serializable/Externalizable を実装しておらず、API は複製をサポートしていません。クローンを強制しようとすると、将来の Java バージョンで機能しなくなる可能性がある回避策になります。

  • cycle.jsを使用してバインディングを JSON にシリアライズします。オブジェクト参照を の形式でエンコードします{$ref: PATH}。逆シリアル化すると、参照が復元されます。

    私が知る限り、cycle.jsは関数をシリアライズしませんが、Function.toString() を使用して自分で関数のシリアライズを追加することは可能です (以下とを参照) 。

または、ライブラリを使用できない場合は、ニーズに合わせて独自のシリアル化を実装するのはかなり簡単です。

var jsonString = JSON.stringify(obj, function(key, val) {
    if (typeof(value) === 'function')
        return val.toString();
    // or do something else with value like detect a reference
    return val
})
于 2014-07-11T09:49:23.003 に答える