Managing Binary Compatibility in Scala (Scala Days 2011)
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Managing Binary Compatibility in Scala (Scala Days 2011)

on

  • 3,534 views

The following is the abstract submitted for my Scala Days 2011 talk: ...

The following is the abstract submitted for my Scala Days 2011 talk:

Binary compatibility is not a topic specific to the Scala language, but rather a concern for all languages targeting the JVM, Java included. Scala shares with Java many sources of potential binary incompatibilities, however, because of Scala greater expressiveness, Scala code has unique sources of incompatibility.

The Scala programming language offers several language constructs that do not have an equivalent in Java and are not natively supported by the JVM. Because of this, the Scala compiler (scalac) transforms these constructs into lower-lever, Java compatible, patterns that can be then easily translated into bytecode. Good examples of such high-level Scala constructs are traits, for mixin-based inheritance, and functions as first data citizens.

During this presentation we will review the main sources of binary incompatibility for the Scala language, providing you with useful insights about how you should evolve your codebase to avoid binary incompatibilities. Furthermore, we will show a tool, the Migration Manager, that can be used to automatically diagnose binary incompatibilities between two versions of a same library.

Statistics

Views

Total Views
3,534
Views on SlideShare
3,512
Embed Views
22

Actions

Likes
5
Downloads
44
Comments
0

5 Embeds 22

https://twitter.com 10
http://www.linkedin.com 5
http://dschool.co 3
http://www.techgig.com 2
https://www.linkedin.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Managing Binary Compatibility in Scala (Scala Days 2011) Presentation Transcript

  • 1. Managing Binary Compatibility in Scala Mirco Dotta Typesafe June 3, 2011 Mirco Dotta Managing Binary Compatibility in Scala
  • 2. Introduction Sources of Incompatibility ConclusionOutline Introduction Example Scala vs. Java Sources of Incompatibility Type Inferencer Trait Conclusion Mirco Dotta Managing Binary Compatibility in Scala
  • 3. Introduction Sources of Incompatibility Conclusion Example Scala vs. JavaExample Assume Analyzer is part of a library we produce. We decide that its API has to evolve as follows:class Analyzer { // old version class Analyzer { // new version def analyze(issues: HashMap[ , ]) {...} def analyze(issues: Map[ , ]) {...}} } Further, assume the next expression was compiled against the old library new Analyzer().analyze(new HashMap[Any,Any]()) Would the compiled code work if run against the new library? The answer lies in the bytecode... Mirco Dotta Managing Binary Compatibility in Scala
  • 4. Introduction Sources of Incompatibility Conclusion Example Scala vs. Java Example: Bytecode Let’s take look at the generated bytecode for the two versions:class Analyzer { // old version class Analyzer { // new version analyze(Lscala/collection/immutable/HashMap);V analyze(Lscala/collection/immutable/Map);V}} }} The expression compiled against the old library would look like: ... invokevirtual #9;// #9 == Analyzer.analyze:(Lscala/collection/immutable/HashMap;)V ⇒ The method’s name has been statically resolved at compile-time. Running it against the new library would result in the JVM throwing a NoSuchMethodException. ⇒ The evolution of class Analyzer breaks compatibility with pre-existing binaries. Mirco Dotta Managing Binary Compatibility in Scala
  • 5. Introduction Sources of Incompatibility Conclusion Example Scala vs. JavaIs Binary Compatibility a Scala issue? The short answer is No. The discussed example can be easily ported in Java. Scala shares with Java many sources of binary incompatibility. But Scala offers many language features not available in Java: Type Inferencer First-class functions Multiple inheritance via mixin composition (i.e., traits) . . . Just to cite a few. ⇒ Scala code has new “unique” sources of binary incompatibility. Mirco Dotta Managing Binary Compatibility in Scala
  • 6. Introduction Sources of Incompatibility Conclusion Type Inferencer TraitType Inferencer: Member Signature Does the following evolution break binary compatibility? class TextAnalyzer { // old version class TextAnalyzer { // new version def analyze(text: String) = { def analyze(text: String) = { val issues = Map[String,Any]() val issues = new HashMap[String,Any]() // ... // ... issues issues }} }} Question What is the inferred return type of analyze? Let’s compare the two methods’ signature.class TextAnalyzer { // old version class TextAnalyzer { // new version public scala.collection.immutable.Map public scala.collection.immutable.HashMap analyze(java.lang.String); analyze(java.lang.String);} } Mirco Dotta Managing Binary Compatibility in Scala
  • 7. Introduction Sources of Incompatibility Conclusion Type Inferencer TraitType Inferencer: Member Signature (2) Question Can we prevent the method’s signature change? That’s easy! The method’s return type has to be explicitly declared: class TextAnalyzer { // bytecode compatible new version def analyze(text: String): Map[String,Any] = { val issues = new HashMap() // ... issues }} Take Home Message Always declare the member’s type. If you don’t, you may inadvertently change the member’s signature. Mirco Dotta Managing Binary Compatibility in Scala
  • 8. Introduction Sources of Incompatibility Conclusion Type Inferencer TraitTrait Compilation Traits are a powerful language construct that enables multiple-inheritance on top of a runtime – the JVM – that does not natively support it. Understanding how traits are compiled is crucial if you need to ensure release-to-release binary compatibility. So, how does the Scala compiler generate the bytecode of a trait? There are two key elements: A trait is compiled into an interface plus an abstract class containing only static methods. “Forwarder” methods are injected in classes inheriting traits. Mirco Dotta Managing Binary Compatibility in Scala
  • 9. Introduction Sources of Incompatibility Conclusion Type Inferencer TraitTrait Compilation Explained An example will help visualize how traits get compiled: // declared in a library trait TypeAnalyzer { def analyze(prog: Program) {...} } // client code class TypingPhase extends TypeAnalyzer The following is the (pseudo-)bytecode generated by scalac:interface TypeAnalyzer { class TypingPhase implements TraitAnalyzer { void analyze(prog: Program); // forwarder method injected by scalac} void analyze(prog: Program) {abstract class TypeAnalyzer$class { // delegates to implementation static void analyze($this: TypeAnalyzer, TypeAnalyzer$class.analyze(this,prog) prog: Program) { } // the trait’s method impl code } }} Mirco Dotta Managing Binary Compatibility in Scala
  • 10. Introduction Sources of Incompatibility Conclusion Type Inferencer TraitTrait: Adding a concrete method Question Can we add a member in a trait without breaking compatibility with pre-existing binaries?trait TypeAnalyzer { // new version // compiled against the old version def analyze(prog: Program) {...} class TypingPhase implements TraitAnalyzer { def analyze(clazz: ClassInfo) {...} // forwarder method injected by scalac} void analyze(prog: Program) { // delegates to implementation TypeAnalyzer$class.analyze(this,prog)//TypeAnalyzer trait compiled }interface TypeAnalyzer { // missing concrete implementation! void analyze(prog: Program); ??analyze(clazz: ClassInfo)?? void analyze(clazz: ClassInfo); }}abstract class TypeAnalyzer$class { static void analyze($this: TypeAnalyzer, Take Home Message prog: Program{...} static void analyze($this: TypeAnalyzer, Adding a concrete method in a trait clazz: ClassInfo) {...} breaks binary compatibility.} Mirco Dotta Managing Binary Compatibility in Scala
  • 11. Introduction Sources of Incompatibility Conclusion Conclusion Future Work Scala Migration ManagerConclusion Ensuring release-to-release binary compatibility of Scala libraries is possible. Though, sometimes it can be difficult to tell if a change in the API of a class/trait will break pre-existing binaries. In the discussed examples we have seen that: Type inferencer may be at the root of changes in the signature of a method. Traits are a sensible source of binary incompatibilities. It really looks like library’s maintainers’ life ain’t that easy... Mirco Dotta Managing Binary Compatibility in Scala
  • 12. Introduction Sources of Incompatibility Conclusion Conclusion Future Work Scala Migration ManagerIntroducing the Scala Migration Manager (MiMa) Today we release the Scala Migration Manager! (beta) It’s free!! It will tell you, library maintainers, if your next release is binary compatible with the current one. It will tell you, libraries users, if two releases of a library are binary compatible. MiMa can collect and report all sources of “syntactic” binary incompatibilities between two releases of a same library. “Syntactic” means NO LinkageError (e.g., NoSuchMethodException) will ever be thrown at runtime. Now it’s time for a demo! Mirco Dotta Managing Binary Compatibility in Scala
  • 13. Introduction Sources of Incompatibility Conclusion Conclusion Future Work Scala Migration ManagerFuture Work Reporting binary incompatibilities is only half of the story. We are already working on a “companion” tool that will help you migrate binary incompatibilities. For the reporting there are many ideas spinning around. Your feedback will help us decide what brings you immediate value One that I believe is useful: Maven/Sbt integration. Mirco Dotta Managing Binary Compatibility in Scala
  • 14. Introduction Sources of Incompatibility Conclusion Conclusion Future Work Scala Migration ManagerScala Migration Manager Visit http://typesafe.com/technology/migration-manager More information about the Migration Manager Download it and try it out, it’s free! We want to hear back from you. Success stories Request new features Report bugs Want to know more, make sure to get in touch! Mirco Dotta, email: mirco.dotta@typesafe.com, twitter: @mircodotta Mirco Dotta Managing Binary Compatibility in Scala