#226 Bundling exception request for byteman
Closed: Fixed None Opened 11 years ago by goldmann.

Hi FPC,

It seems that one of my packages requires bundled software. Explanation and reasoning you can find below. This package is currently available in Fedora in unbundled state to meet Fedora packaging guidelines. Sadly this process removed the core functionality of this tool which made it unusable.

Homepage: http://www.jboss.org/byteman

This project is very valuable when testing/debugging application running on JVM. Please consider granting exception for this package.

The project leader of Byteman is added to CC.

Thanks!


Byteman provides functionality akin to Systemtap but for Java deployments, enabling dynamic modification of Java code belonging bothto application programs and to the Java runtime itself. Like Systemtap,Byteman can be used simply for tracing or performance measurement but italso supports injection of code during unit and integration testingwhich side effects the application or runtime state to generate andpropagate faults, making it simple to engineer complex test scenarios.

Byteman hooks into a capability provided by the Java virtual machinewhich allows it to modify Java bytecode as the virtual machine isexecuting. It can dynamically redefine and relink bytecode to addbehaviour not included in the original source code. It can also removeinjected behaviours later on -- in fact it can retransform the bytecodeas often as you ask it to.

In order to perform this redefinition and relinking Byteman potentiallyneeds to make its own code and the library code it depends on visible inevery executable scope (in practice the only dependency is the ASMlibrary -- a bytecode rewriting tool). In particular, this means thatByteman and its libraries need to be visible in system scope (i.e. theyneed to be able to be linked into virtual machine runtime code). If anapplication wants to use the ASM library (and many applications,including our own JBoss applications, do need to) then when Bytemanmakes the code visible in system scope it is very likely to break theapplication when it tries to link against the code in its ownapplication scope. Invariably this will lead to the code being linkedpartially against one copy of the library and partially against anothercopy. This will happen '''even if these are two copies of the same library'''.

In order to avoid this link-time clash Byteman needs to be bundled witha modified version of its dependent libraries (i.e. ASM) transformed sothat the symbols in the bundled code are exported and then referencedfrom Byteman using names belonging to the (private) Byteman namespace.


We're not sure we completely understand. Can you be more specific about what components need to be bundled? Is this just the ASMlibrary? If so, is it just a transformed version of the ASMlibrary? Could the ASMlibrary package generate a special "transformed" version as part of its normal build process that byteman could Require (and use)?

Hi Spot,

Yes, this is all about bundling ASM with Byteman in its private namespace. No, unfortunately Byteman cannot work with anything available outside of its scope, because it'll break it functionality as described above (linkage problems). ASM needs to be part of Byteman.

If you need any additional info, I'll try to provide it, let me know.

Is there no way to have the ASM package spit out an "asm-byteman" subpackage with the ASM library configured as needed for byteman? I just really do not like the idea of having a disconnected ASM bundled inside byteman, since that is very likely to get out of sync.

Unfortunately we cannot go this route, since this doesn't solve the problem (Java internals; class loading/linkage). Most probably there will be no changes made to the ASM library code, it just needs to be in the same context as Byteman.

I'll contact Andrew and ask him for a more verbose description on why this isn't possible, since I'm not a Java internals guru :)

Replying to [comment:3 spot]:

Is there no way to have the ASM package spit out an "asm-byteman" subpackage with the ASM library configured as needed for byteman? I just really do not like the idea of having a disconnected ASM bundled inside byteman, since that is very likely to get out of sync.

Hi Spot,

Marek and I considered your suggestion when we discussed this problem some months back and, yes, it is indeed /possible/ to do something like this. I am not sure how much of an improvement it is though. I don't know if it will be any simpler to ensure we spit out a transformed version of ASM when a new version is deployed than it is simply to rebuild and redeploy Byteman whenever ASM is rebuilt and redeployed. We would need to bullet proof the update process to make sure the old transformed version is guaranteed to be removed/overwritten by a new version.

This solution does not seem right to me anyway. If ASM ever does need to be updated then Byteman probably ought to be rebuilt and retested also as a follow-up to the ASM update. We need to know it still works with the modified ASM release. So, just remembering to rebuild it seems to me to be a far simpler solution than trying to generate, and regenerate a separate 3rd party jar. After all building and testing Byteman is already automated. Reapplying this known process has the added advantage that the Byteman built and deployed in Fedora will be no different to the one distributed for other platforms via maven central. Your suggestion will mean providing a special Fedora build.

Leaving the above arguments aside, Marek's follow-up refers to another source of complexity that your solution does not address. One reason for locating the transformed ASM code in the byteman jar -- apart from the name clash issue -- is that the agent code in the jar and its dependencies need to be deployed as a unit. When an agent is being used to transform code at runtime it may need to be loaded in different scopes. In Byteman's case it is sometimes necessary to load the agent in the bootstrap scope or in the system scope, depending upon what the user wants to do with it. The former is necessary if you want to be able to modify the behaviour of certain core classes in the Java runtime such as Thread, System, FileOutputStream etc. The latter ensures that these classes cannot be modified.

With the ASM code bundled in the byteman jar both sets of code are always visible in the same scope. If they are independently loadable then they can end up in different scopes and this will break things. Now, it is possible to automate the various Byteman tools and scripts which complement the Byteman agent so that when on Fedora they attempt to install the two separate ASM and Byteman agent jars in the same scope. Once again this adds complexity and introduces differences between the Fedora release and the non-Fedora release, complexity which I don't really want to have to manage.

Unfortunately, there is the more important concern that Byteman also needs to be used from the java command line and configured for use from maven and ant. Separating the two jars will also require educating users how to do this right, making Fedora a special case and a more complex case for end users to manage. I know from experience that many users find these loading issues difficult to understand and don't really want to have to focus on such things rather than get on with using Byteman. So, I don't really want to make this any more difficult than it needs to be.

Okay. Thinking out loud here, if the Fedora Byteman package:

  • Removed the bundled copy of ASM
  • BuildRequires: ASM
  • Generates the transformed ASM code that Byteman needs from the prebuilt ASM package
  • Bundles a copy of that transformed ASM jar file
  • Has a strict versioned Requires: ASM (down to the version and release), not because Byteman is using it, but to ensure that if anything changes in ASM, Byteman will have a broken dependency until it is rebuilt.

That might work. What are your thoughts on that?

Replying to [comment:6 spot]:

Okay. Thinking out loud here, if the Fedora Byteman package:

  • Removed the bundled copy of ASM
  • BuildRequires: ASM
  • Generates the transformed ASM code that Byteman needs from the prebuilt ASM package
  • Bundles a copy of that transformed ASM jar file
  • Has a strict versioned Requires: ASM (down to the version and release), not because Byteman is using it, but to ensure that if anything changes in ASM, Byteman will have a broken dependency until it is rebuilt.

That might work. What are your thoughts on that?

That sounds to me like an excellent solution.

Replying to [comment:6 spot]:

Okay. Thinking out loud here, if the Fedora Byteman package:

  • Removed the bundled copy of ASM
  • BuildRequires: ASM
  • Generates the transformed ASM code that Byteman needs from the prebuilt ASM package
  • Bundles a copy of that transformed ASM jar file
  • Has a strict versioned Requires: ASM (down to the version and release), not because Byteman is using it, but to ensure that if anything changes in ASM, Byteman will have a broken dependency until it is rebuilt.

That might work. What are your thoughts on that?

Technically I would use the maven-shade-plugin, just like upstream does and add the strict BuildRequires bits. I'll make sure byteman package will be rebuilt every time objectweb-asm package gets updated. Does it make sense?

The byteman package should additionally include (via http://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries#Requirement_if_you_bundle):

{{{
Provides: bundled(objectweb-asm) = ASMVERSION
}}}

Correct?

I don't understand what the maven-shade-plugin has to do with this at all. The Requires is important, because I want to ensure that we have a check to force the rebuild if objectweb-asm changes (and it isn't that I don't trust you, but I want this check to be future-proof).

The additional Provides seems correct.

Please note: This is just my proposal, the FPC hasn't voted on it yet.

Replying to [comment:9 spot]:

I don't understand what the maven-shade-plugin has to do with this at all. The Requires is important, because I want to ensure that we have a check to force the rebuild if objectweb-asm changes (and it isn't that I don't trust you, but I want this check to be future-proof).

The maven-shade-plugin is just the technical detail of implementation for step #3 and #4 from your proposal. I completely understand the reasoning behind full requires with version and release and I don't argue with it :)

Replying to [comment:6 spot]:

Okay. Thinking out loud here, if the Fedora Byteman package:

  • Removed the bundled copy of ASM
  • BuildRequires: ASM
  • Generates the transformed ASM code that Byteman needs from the prebuilt ASM package
  • Bundles a copy of that transformed ASM jar file
  • Has a strict versioned Requires: ASM (down to the version and release), not because Byteman is using it, but to ensure that if anything changes in ASM, Byteman will have a broken dependency until it is rebuilt.

  • byeman has a virtual Provides: bundled(objectweb-asm) = ASMVERSION

The FPC passed this proposal today. (+1: 7, 0: 0, -1: 0)

We noted that it is something of a hybrid of a static library and bundled library approach which seems sound. I'll add the virtual provides to our table.

announcement writeup:

Due to the special way in which byteman uses the objectweb-asm library, byteman was granted an exception to bundle objectweb-asm using a hybrid static-library bundling approach. Please see the ticket if you wish details of how this approach works. https://fedorahosted.org/fpc/ticket/226

I'm very sorry but I am afraid I have overlooked a second dependency which needs to be taken into account here.

Byteman's rule parser uses 4 relatively small classes from the javacup jar i.e. the code in package java_cup.runtime. java_cup is a parser generator which generates parser code from a grammar file. The 4 classes in the dependency implement the runtime driver which calls into the generated parser and tokenizer classes for Byteman's rule language. Byteman cannot operate without this rule parser.

The situation is much the same as with ASM. Firstly, these 4 classes need to be renamed and bundled in order to avoid namespace clashes with user code. That requirement is not really hard since java_cup is used far less than ASM. A name clash in an application Red Hat cares about is very unlikely.

However, the second and most important reason they need to be bundled in the Byteman jar (renamed or not) is so they are guaranteed to be loaded into system or bootstrap scope along with the Byteman code. If the jar is only available via the classpath then injection into bootstrap code will break. As with ASM, ensuring that the byteman and java_cup jars both get loaded together involves changing the Byteman scripts on Fedora and, worse, educating users to get this right in their ant/maven scripts and on the
command line.

So, yes, the java_cup jar really needs to be included as a 2ndary dependency and, I assume, requires an extension to the exemption plus, perhaps, inclusion of the relevant jar in Fedora.

Having checked through the build process I can guarantee that there are no further bundling dependencies and I certainly cannot foresee that there will ever need to be others. I can only apologise again that I did not identify this requirement earlier.

regards,

Andrew Dinn

For what it is worth, I think I'd be willing to grant a blanket exception for byteman to handle any other necessary components in exactly the same way we approved the ASM exception. So, assuming that we can treat java_cup (and any other java component) identical to the method approved for ASM, this should not be an issue. (Please note, again, this is just my opinion, FPC will need to vote for a blanket exception)

java_cup is already packaged in Fedora.

Replying to [comment:14 spot]:

For what it is worth, I think I'd be willing to grant a blanket exception for byteman to handle any other necessary components in exactly the same way we approved the ASM exception.

That would work for me too. +1

Any chance to add it to a meeting and perform a formal vote on a blanket exception for Byteman?

I likely won't be around for the meeting. please count my +1 for spot's proposal.

Can we move this ticket forward?

additional bundling for byteman passes (+1: 5, 0: 1, -1: 0)

go ahead and use:
Provides: bundled(java_cup) = JAVACUPVERSION

and I'll add that particular one to the page now.

Login to comment on this ticket.

Metadata