Mixing Java 1.4 and 1.6 bytecode in a class hierar

2019-02-15 23:25发布

The question first, the story will follow:

Is it safe to mix different bytecode version in a class hierarchy? What are the risks?

For a case, Class C extends B, Class B extends Class A. Class A implements Interface I. My question would involve following example scenarios:

  • Class A compiled to Java 1.6 bytecode, and have 1.6 features such as generics, etc. The heirs, which are B and C was compiled to 1.4 bytecode.
  • Interface I compiled to 1.6, while the implementor compiled to 1.4.
  • Other exotic inheritance scenario involving different version of bytecode.

I have tried as many scenarios I could imagine and it seems to run just fine. However I still feel the urge to ask here as I only know Java at the surface; i know how to code and tweak Java but don't really know what happen under the hood.

Now for those minds who can't help themselves to ask "why would you need to do that???".

I'm in a project to assess the migration of legacy Java 1.4 Swing app, connected to EJB 2 via RMI, to Java 1.6 Swing connected to newer version of App Server running on top of 1.6 also. The J2EE platform will still be 1.4 (EJB 2).

The migration will not be "recompile everything to 1.6", but it will be "code and compile new features to 1.6". The way they do things is like this: They only have one path in the CVS, everyone commits there. No tags/branches whatsoever to get the production code. Whenever a new feature need to be added, they get the JARs from production server, explode them, replace or add new classes as needed, repackage the jars, put them back to server. Therefore, if they will use Java 6 to compile and using the above method for deployment, there will be a lot of exotic mixes of 1.4 and 1.6 bytecodes.

标签: java bytecode
5条回答
2楼-- · 2019-02-16 00:08

These links seem relevant. They document the few edge cases that could break compatibility between 1.4 and 1.5 and between 1.5 and 1.6.

The biggest differences that could cause problems that I can think of is that enum became a keyword, but that would only effect a 1.5+ JVMs when loading an older class file (which doesn't seem to be what you will be doing). The other thing is annotations. The above links seem to suggest everything would be fine, but I would be wary about what would happen if an older JVM loaded up a class with runtime annotations.

Other than that I don't think there have been any bytecode changes between the first version of java and java 6. Meaning the only problems you should encounter are changes to functionality the API or deprecations (listed in the links above).

查看更多
We Are One
3楼-- · 2019-02-16 00:08

As long as you aren't using reflection, the only major problem you could have from differing bytecode versions is the ACC_SUPER flag.

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.

However, these don't directly affect the bytecode execution. The only way these have an affect is if you access them through reflection. For instance, java.lang.Class.getDeclaredClasses() will return information from the optional attribute InnerClasses.

查看更多
狗以群分
4楼-- · 2019-02-16 00:13

You can compile with Java 6 but target 1.4 with a compiler setting. We did this for a migration project once. If/when 1.4 disappears, you then change your compiler settings again and target 1.6.

Keeping the target version explicit also means that you can upgrade your SDK without fear of your JAR files becoming unusable to an older JVM.

查看更多
Summer. ? 凉城
5楼-- · 2019-02-16 00:14

I am maintaining an environment with mix of 1.4 (old library jars) and 1.5 (my fixes and stuff) classes on Tomcat using Sun JVM 1.5 and it runs fine.

However, for RMI you may be in trouble if client and server has different class version because the server might check the class version (I ran into this problem).

The best way to find out is to do a proof of concept type of project on small scale.

A friendly reminder though, you are digging a pretty big hole for yourself here :-)

查看更多
Deceive 欺骗
6楼-- · 2019-02-16 00:27

The JVM byte code is not siginificantly different between Java 1.0 and Java 6. In Java 7 they add one new instruction. Woohoo.

There are so little changes in how the byte code works that

  • The JVM doesn't support nested classes accessing private members of outer classes, this works through generated code.
  • The JVM doesn't support runtime checks for generics e.g you cannot new T() where T is a generic.

Basically, they make the JVM smarter and faster but until recently changing the model of how the byte code works has been avoided at all costs.

查看更多
登录 后发表回答