Hi I'm trying to use multiple versions of a packag...
# community-support
d
Hi I'm trying to use multiple versions of a package that has an identical classpath. Is there a way to relocate each version of these plugins to custom locations (like org.example -> org.example.v1)? I know there is the shadow plugin but it seems to only support relocating the entirety of that classpath which seems like it would relocate all the versions to the same spot. Is there another way to do this? Thanks!
m
What code is calling into the different version and how does it know which version ends up running?
d
I'm designing a wrapper that will take the version number as input and output the method or object in question. Depending on the implementation details might make specific wrapper methods for the method/object api calls I'm using to account for changes in variable naming
m
So the code that calls your lib is in a different jar file, right?
If that's the case I'm not sure I follow. You could relocate
lib:1
,
lib:2
, etc.. separately (with different package names) and then have your wrapper call into the different packages
d
The code is part of my main class with jar dependencies. I need to create an object that has methods that will either call one package version or the other. Normally I'd use class loaders but I'm in a graalvm native image which won't have the JVM and class loaders so I'd have to do everything in the build phase so the only option I see is to move each jar version to its own unique location on the classpath
m
Then relocate them each one separately?
d
Yeah pretty much put them into separate class locations so if each had a classpath of org.example.* it'd be org.example.v1.*
m
I think you mean
package name
instead of
classpath
?
A jar doesn't really have a classpath
d
Yeah I mean how it's api calls that you import appears in terms of the classpath
m
So you have
lib-1.jar
containing
com.example.Hello.class
and
lib-2.jar
containing the same symbol
com.example.Hello.class
except with a different implementation
d
Yeah that's correct
m
Now you can relocate
lib-1.jar
with
relocate("com.example", "com.example.v1")
and
lib-2.jar
with
relocate("com.example", "com.example.v2")
d
Technically each package is split up into multiple jars with .so files connected through JNI
m
Ah, JNI might make things a bit more complicated but I know nothing about JNI
d
Would that work with them both being com.example as based on my understanding it'd do that on everything under that classpath
m
I'm not sure I follow. If you do what I suggested above, you will end up with: •
lib-1-shadow.jar
containing
com.example.v1.Hello
lib-2-shadow.jar
containing
com.example.v2.Hello
Then you can code your wrapper on top of those 2 libraries
Ah, I see what you mean with "classpath"
Shadow wants you to relocate in the context of a Gradle project, not sure if you can relocate a single
.jar
There has to be a way, it's just not super well documented IMO
d
Yeah wasnt sure if I can do it with just the jars
m
Yea, this is probably what you want. If you add both
lib-1.jar
and
lib-2.jar
to the dependencies of your project it's too late
You want to shadow them separately before adding
lib-1-shadow.jar
and
lib-2-shadow.jar
as dependencies
I would do this using a Gradle artifact transform
v
Especially with JNI in play I doubt any relocation will work. You would probably need to have separate processes for the libs and dispatching calls to those or something like that.
m
Yea JNI sounds not easy
The machine code contains references to the Java packages, right? Meaning you'd need to also relocate mach-O, elf files, etc...
Or separate processes indeed
d
Possibly I'm not too familiar with what the .so files perform, I suppose that's where manual byte manipulation like with ASM?
m
ASM can deal with your
.jar
files. The
.so
is probably a lot more involved because depending the OS, it's a different file format, etc....
d
Gotcha are there any other alternatives to handle the .so files?
I'll still try the above method and see if it just works lol
v
Even if you could change the package name in the native lib. You would also need to change its identity and loading, because you cannot load a native library twice in the lifetime of a JVM.