Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule to restrict to specific bytecode java version #423

Open
pjroth opened this issue Sep 10, 2020 · 7 comments · May be fixed by #1418
Open

Rule to restrict to specific bytecode java version #423

pjroth opened this issue Sep 10, 2020 · 7 comments · May be fixed by #1418

Comments

@pjroth
Copy link

pjroth commented Sep 10, 2020

Hi, I can't seem to determine how to accomplish my use case. Any help would be greatly appreciated.

Is it possible to verify that a jar I create is compiled to java 8 or below including all dependencies used by that jar?

I don't see anything in the API to check for bytecode version but I might just be missing it.

Thank you,
Peter

@codecholeric
Copy link
Collaborator

Unfortunately this is not possible at the moment, because nobody ever had a use case for it 🤔 It is easily possible to read the byte code version of the imported class AFAIS, but so far the info is simply ignored.
What I don't understand is your point "including all dependencies", because either these dependencies are themselves "objects under test" and directly inspected by an ArchRule, or they are external, but then it does not really make sense to test them, since in any other scenario they could be swapped out against versions that have a different bytecode version. Or am I understanding this wrongly?

@pjroth
Copy link
Author

pjroth commented Sep 26, 2020

It is easily possible to read the byte code version of the imported class
Is it possible using the current API or possible that it could be added?

Regarding the dependencies I agree these could be swapped out by clients. But i can’t control that of course. What i would like to do is protect myself from adding a dependency to my project that doesn’t meet the minimum bytecode requirement my project has.

To give more background. I have an SDK that is used to access one of our REST APIs. That SDK has a requirement for java 7 or lower. I just had a bug in this project however because I updated a dependency version to the latest version. This is our usual process to update dependencies when working on a project. However, many java libraries do not make it easy to determine the bytecode they are compiled to. So i inadvertently added a dependency that uses java 8 when the previous version was java 7 even though I looked at the docs, I didn’t look hard enough though. This then broke one of the clients (in another project at the same company) that uses this SDK.

I would love to write a test to protect myself from this. I fully understand this only will work if the project using my SDK doesn’t change this dependency version but we can’t solve all the problems. Although maybe I could shade to avoid this. That can be a discussion for another day perhaps. :)

Thanks for the response. Have a great day!

@hankem
Copy link
Member

hankem commented Sep 27, 2020

Would running your test suite with a JRE 7 catch such bugs?

@codecholeric
Copy link
Collaborator

I also feel like the only way to really be sure it works with JRE 7 is to test it with JRE 7 🤔 That's by the way also what ArchUnit does itself 😉 Because sometimes even though the bytecode would be compatible there still is some incompatibility in implementation/behavior...

@pjroth
Copy link
Author

pjroth commented Sep 27, 2020

I think running the tests with JRE 7 would catch these types of bugs for sure. What i don’t prefer though is now the developer and CI environment setups get more complex. It is becoming harder and harder to even get old JREs. I was hoping for a solution that allows me to install one JDK. Now with java 9+ and the ‘release’ flag it makes compiling to older versions much easier and less error prone. At the moment I install only java 11 but i can compile all the way back to 7.

All this has made me wonder why the maven coordinates don’t support an option for specifying the bytecode version. 🤔 Although I believe that multi-version jars are a newish thing too when using java modules.

@pjroth
Copy link
Author

pjroth commented Sep 29, 2020

So is there anything you could imagine adding to ArchUnit to help with my use case or do we just say I should really be testing with the target JRE I require? From my perspective, I would much prefer to just add a simple test case rather than configuring multiple JREs for tests (which is far more complex). But I understand if this use case is perhaps outside the goals of ArchUnit.

@codecholeric
Copy link
Collaborator

I could well imagine to add this to ArchUnit (to know which version of byte code was imported seems to be just fair, if we also have things like the respective source file or even an MD5 sum of the imported class if activated).
My personal problem is, that I don't have the capacity at the moment to implement it. If you (or anybody else) would want to give it a shot to create a PR, I'm more than happy to support you / merge it!

The entry point would be

com.tngtech.archunit.core.importer.JavaClassProcessor.visit(int version, ...) {...}

And in fact AFAIS this first parameter version is exactly the bytecode version (even though there seems to be some caveat that major and minor version are encoded together into this integer 🤔 So it might be sth. like version & 0x0000FFFF and version & 0xFFFF0000 to parse major and minor version, see Javadoc).
It should be simply adding this as property to JavaClassBuilder and that's it 🤔 Maybe it would be nice to have a JavaClassVersion where you could ask for classVersion.getByteCodeMajorVersion() and classVersion.getJavaVersion() to easier map sth. like 51 to Java 7 🤔 Anyway, the mapping can e.g. be found in https://fabianlee.org/2018/01/19/java-determining-the-java-version-used-to-compile-a-class-class-file-has-the-wrong-version/ (don't know if there is any highly official source 😉).
I'm really sorry that I can't do it myself at the moment, but I really want to push for the Generics support with all the (very limited) capacity I have at the moment! 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants