1

最初の質問、物語は続きます:

クラス階層で異なるバイトコードバージョンを混在させても安全ですか?リスクは何ですか?

あるケースでは、クラスCはBを拡張し、クラスBはクラスAを拡張します。クラスAはインターフェイスIを実装します。私の質問には、次のシナリオ例が含まれます。

  • クラスAはJava1.6バイトコードにコンパイルされ、ジェネリックなどの1.6の機能を備えています。BとCの相続人は1.4バイトコードにコンパイルされました。
  • インターフェイスは1.6にコンパイルしましたが、実装者は1.4にコンパイルしました。
  • 異なるバージョンのバイトコードを含む他のエキゾチックな継承シナリオ。

私は想像できる限り多くのシナリオを試しましたが、うまくいくようです。しかし、私は表面上はJavaしか知らないので、ここで質問したいという衝動をまだ感じています。私はJavaのコーディングと微調整の方法を知っていますが、内部で何が起こっているのか本当にわかりません。

さて、「なぜあなたはそれをする必要があるのか​​?」と自問するのを助けることができないそれらの心のために。

私は、RMIを介してEJB2に接続されているレガシーJava1.4 Swingアプリから、1.6上で実行されている新しいバージョンのAppServerに接続されているJava1.6Swingへの移行を評価するプロジェクトに参加しています。J2EEプラットフォームは1.4(EJB 2)のままです。

移行は「すべてを1.6に再コンパイル」するのではなく、「新機能を1.6にコード化してコンパイルする」ことになります。彼らのやり方は次のようなものです。CVSにはパスが1つしかないので、全員がそこでコミットします。プロダクションコードを取得するためのタグ/ブランチは一切ありません。新しい機能を追加する必要があるときはいつでも、本番サーバーからJARを取得し、それらを分解し、必要に応じて新しいクラスを置き換えまたは追加し、jarを再パッケージ化して、サーバーに戻します。したがって、Java 6を使用してコンパイルし、上記のデプロイメント方法を使用する場合、1.4バイトコードと1.6バイトコードのエキゾチックな組み合わせが多数存在します。

4

5 に答える 5

3

Java 6でコンパイルできますが、コンパイラ設定で1.4をターゲットにします。これは、移行プロジェクトで一度行いました。1.4が消えた場合は、コンパイラ設定を再度変更して1.6をターゲットにします。

ターゲットバージョンを明示的に保つことは、JARファイルが古いJVMで使用できなくなることを恐れずにSDKをアップグレードできることも意味します。

于 2012-04-19T08:56:24.867 に答える
3

JVMバイトコードは、Java1.0とJava6の間で大きな違いはありません。Java7では、1つの新しい命令が追加されます。ウーフー。

バイトコードの動作にはほとんど変更がありません。

  • JVMは、外部クラスのプライベートメンバーにアクセスするネストされたクラスをサポートしていません。これは、生成されたコードを介して機能します。
  • JVMは、ジェネリックのランタイムチェックをサポートしていません。たとえばnew T()、Tがジェネリックである場合はサポートできません。

基本的に、これらはJVMをよりスマートかつ高速にしますが、最近まで、バイトコードの動作モデルを変更することは絶対に避けられていました。

于 2012-04-19T09:01:56.937 に答える
2

私は、Sun JVM 1.5を使用するTomcatで1.4(古いライブラリjar)クラスと1.5(私の修正など)クラスが混在する環境を維持しており、正常に動作します。

ただし、RMIの場合、サーバーがクラスバージョンをチェックする可能性があるため、クライアントとサーバーのクラスバージョンが異なると、問題が発生する可能性があります(この問題が発生しました)。

見つけるための最良の方法は、小規模なプロジェクトの概念実証タイプを行うことです。

フレンドリーなリマインダーですが、あなたはここであなた自身のためにかなり大きな穴を掘っています:-)

于 2012-04-19T09:09:46.187 に答える
1

これらのリンクは関連しているようです。それらは、 1.4と1.5間および1.5と1.6の間の互換性を壊す可能性のあるいくつかのエッジケースを文書化しています。

私が考えることができる問題を引き起こす可能性のある最大の違いは、列挙型がキーワードになったということですが、それは古いクラスファイルをロードするときに1.5以上のJVMにしか影響しません(これはあなたがやろうとしていることではないようです)。もう1つは注釈です。上記のリンクは、すべてがうまくいくことを示唆しているようですが、古いJVMがランタイムアノテーションを使用してクラスをロードした場合にどうなるかについては注意が必要です。

それ以外は、javaの最初のバージョンとjava 6の間にバイトコードの変更はなかったと思います。つまり、発生する必要がある唯一の問題は、APIの機能の変更または非推奨(上記のリンクにリストされています)です。

于 2012-04-19T09:25:55.757 に答える
1

リフレクションを使用していない限り、バイトコードのバージョンが異なると発生する可能性がある唯一の大きな問題はACC_SUPERフラグです。

In very early versions, invocation of superclass methods was not handled correctly. When they fixed it, they added a new flag to the classfile format, ACC_SUPER to enable it, so that applications relying on the old, broken, behavior were not affected. Naturally, using a class that doesn't contain this flag could cause problems.

However, this is ancient history. Every class compiled in 1.4 and later will have the flag, so this isn't a problem. Bytecode wise, the only major differences between 1.4 and 1.6 are the addition of optional attributes used to store metadata about inner classes, generics, annotations, etc.

ただし、これらはバイトコードの実行に直接影響しません。これらが影響を与える唯一の方法は、リフレクションを介してアクセスする場合です。たとえば、java.lang.Class.getDeclaredClasses()はオプションの属性から情報を返しますInnerClasses

于 2013-04-06T03:04:48.723 に答える