Top Banner
June 10-11, 2008 Berlin, Germany Everything can be a bundle – Making OSGi bundles of Java legacy code Erik Wistrand [email protected] Gunnar Ekolin [email protected]
29

June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand [email protected] Gunnar Ekolin.

Dec 16, 2015

Download

Documents

Michael Casey
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

June 10-11, 2008 Berlin, Germany

Everything can be a bundle – Making OSGi bundles of Java legacy code

Erik [email protected]

Gunnar [email protected]

Page 2: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

2

• Lots of Java code has been written taking stuff for granted• Just one classloader• System.exit() is OK to call• A file system is present• A static main() method is used for start-up• ...

...this leads to classloading problems, premature exit of the entire framework and various internal bugs

What's the problem?

Page 3: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

3

The Knopflerfish OSGi framework contains code that can

• Start jar files with only a static main method• Automatically import/export packages• Patch code that uses “bad” methods regarding

classloading etc.

What can be done?

Page 4: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

4

Installing a non-bundle JAR-file

• The Auto-Manifest feature of Knopflerfish makes it possible to take any jar file and install it as if it where bundle• All contained packages will be exported• Dynamic-Import: * used to get access to shared

packages.

Page 5: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

5

Auto-Manifest - Configuration

The file automanifest.props

1.match.filter=(location=*hello_world-app*)

1.export.filter=(pkg=*)

1.export.file.filter=(file=*.class)

1.header.DynamicImport-Package=*

1.header.Import-Package=[remove]

1.header.Export-Package=[autoexport]

Page 6: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

6

Auto-Manifest - Launch

java -Dorg.knopflerfish.framework.automanifest=true -Dorg.knopflerfish.framework.automanifest.config= file:automanifest.props -Dorg.knopflerfish.framework.debug.automanifest= true -jar framework.jar

Page 7: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

7

Demo: Hello World

• Install the Hello World application hello_world-app-1.0.0.jar

• The demos are available for download fromhttp://www.knopflerfish.org/demos/knopflerfish-osgi-berlin-2008.zip

Page 8: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

8

Main-Class as Activator - Launch

java -Dorg.knopflerfish.framework.automanifest=true -Dorg.knopflerfish.framework.automanifest.config= file:automanifest.props -Dorg.knopflerfish.framework.debug.automanifest= true -Dorg.knopflerfish.framework.main.class.activation= file:jars/hello_world-app/hello_world-app-1.0.0.jar -jar framework.jar

Page 9: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

9

System.exit()

• An application normally calls System.exit(0) to terminate. • This will kill the entire OSGi framework.

• Common workaround:• Modify the application source to be OSGi aware and

recompile.• Impractical.• License issues.• Source may not be available.

Page 10: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

10

Since all bundle classes are loaded via the OSGi framework, the framework can modify the byte-code on the fly to use the correct classloader:

1. Load original byte code.

2. Find occurrences of “wrong” method calls.

3. Replace with call to “right” method.

4. Use the modified class.

(5. Profit!)

A new approach – automatic byte code modification

Page 11: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

11

BundleClassLoader

The Knopflerfish implementation

Bundle Patched BundleASM

patches.props

Page 12: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

12

• Uses the ASM byte-code manipulation library.• A configuration file can specify which

bundles/classes should be modified.• Bundles are automatically modified as they are

loaded.

Yes, this is a poor man's aspect oriented framework.

btw, LDAP filters are the best thing since sliced bread. Yes, they are!

The Knopflerfish implementation

Page 13: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

13

Default set of patches

• java.lang.ClassLoader.getSystemClassLoader()• Returns the bundle classloader.

• java.lang.System.exit(int)• Calls BundleContext.stop(), disabled by default.

• java.lang.Class.forName(String)• First tries the default classloader, then the bundle's classloader.

• java.lang.Class.forName(String,boolean,ClassLoader)• First tries the specified classloader, then the bundle's

classloader.

Page 14: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

14

Patching - Launch

java -Dorg.knopflerfish.framework.patch=true -Dkf.patch.systemExitWrapper=true -cp framework.jar:asm-3.1.jar org.knopflerfish.framework.Main

Page 15: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

15

Demo: Hello World

• Start the Hello World application and stop it by closing the window.

• Same thing again with default bundle patching enabled.

• The demos are available for download fromhttp://www.knopflerfish.org/demos/knopflerfish-osgi-berlin-2008.zip

Page 16: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

16

Classloading problems

• Old, non-OSGi-aware libraries can easily be wrapped as an OSGi bundle.• Sounds easy, just create a manifest file and

export/import the necessary stuff,

...but they may still run into classloading problems.

ClassNotFoundException:Cannot find com.acme.ICustomer

Page 17: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

17

Why ClassNotFoundException

• For the OSGi import/export mechanism to work, the bundle must use the Bundle classloader.

• However, many libraries uses the system classloader or the thread's classloader• Works great in standalone apps• Does not work at all in typical OSGi settings

Page 18: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

18

package mypackage;

class Foo {

System classloader

Bundle classloader

mypackage.Foo.classmypackage.Bar.class

Class c = ...getContextClassLoader().loadClass(“mypackage.Bar”); Class c =

Foo.class.getClassloader().loadClass(“mypackage.Bar”);

OSGi framework

Fails!

ok!

Page 19: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

19

• Modifying the library source to be OSGi-aware and recompile• Impractical• License issues

• Wrapping each library call in code that sets the thread's context class loader• Tricky to find all cases• Boilerplate code is a Bad Thing

• Put all classes on the system class path!• Really just hurts

Common workarounds to fix classloading

Page 20: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

20

Demo – run jEdit as a bundlejEdit bundle

Knopflerfish OSGi + ASM

jEdit 4.2 std distribution

Std OSGi bundles

Wrapper methods

JVM

Page 21: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

21

Let's patch all library calls to

Class.forName(String name, boolean init, ClassLoader cl)

Example patch

Page 22: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

22

public static Class forName3Wrapper(String name,

boolean initialize,

ClassLoader cl,

long bid,

Object context) throws ClassNotFoundException{ // use bundle classloader instead

return ... }

First, write the wrapper method

Page 23: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

23

•Find the string signature of the method to be patched

java/lang/Class.forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;

•Find the string signature or the static wrapper method that should replace the above call

org/knopflerfish/framework/ClassPatcherWrappers.forName3Wrapper

Next, find signature strings

Page 24: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

24

patch.1.from= java/lang/Class.\forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)\Ljava/lang/Class;

patch.1.to= org/knopflerfish/framework/ClassPatcherWrappers.\forName3Wrapper

patch.1.static=true

patch.1.active=true

# Optional LDAP-filter with keys: classname, methodname, methoddesc,

# methodaccess, bid, location and all manifest headers.

patches.filter=(&(!(classname=org.knopflerfish.*))\ (!(classname=org.osgi.*))(location=*))

Create configuration file

Page 25: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

25

Specify Configuration File

• A global (default) patch configuration file can be specified as the value of the (system) property: org.knopflerfish.framework.patch.configurl

• Each bundle can specify a bundle specific patch configuration file via the manifest header:

Bundle-ClassPatcher-Config:!/patches.props

Page 26: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

26

java \ -Dorg.knopflerfish.framework.patch=true \ -Dorg.knopflerfish.framework.patch.configurl=\ file:patches.props \ -cp framework.jar:asm-3.1.jar \org.knopflerfish.framework.Main

...and launch

Page 27: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

27

Upcoming changes

• Today the patching engine is part of the framework.

• It will be moved out to a separate bundle using an API similar to java.lang.instrumentation.ClassFileTransformer

Page 28: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

June 10-11, 2008 Berlin, Germany

Q&A

Gunnar [email protected]

Page 29: June 10-11, 2008 Berlin, Germany Everything can be a bundle – M aking OSGi bundles of Java legacy code Erik Wistrand wistrand@makewave.com Gunnar Ekolin.

June 10-11, 2008 Berlin, Germany

Everything can be a bundle – Making OSGi bundles of Java legacy code

Erik [email protected]

Gunnar [email protected]