• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Extending JRuby
 

Extending JRuby

on

  • 2,008 views

My talk given on Oct 2 2010 at JRubyConf.

My talk given on Oct 2 2010 at JRubyConf.

Statistics

Views

Total Views
2,008
Views on SlideShare
2,004
Embed Views
4

Actions

Likes
3
Downloads
10
Comments
0

2 Embeds 4

http://lanyrd.com 3
http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

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
  • Ruby going on 10 years now <br /> Java stopped being my main programming language ~6-7 years ago. My latest Java in a Nutshell book, is brown and has a referee on the front. Java had a dot in its version at the time. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • have a program <br /> <br /> Need to access some functionality in a third party library, it is either to time consuming to write yourself, or its proprietary, or boring, or so solid no bugs in years. <br /> <br /> The extensions is what sits between the ruby runtime and exposes the funcationality of the Awesome Library to the ruby runtime so that your ruby program can use it. <br /> <br /> <br />
  • have a program <br /> <br /> Need to access some functionality in a third party library, it is either to time consuming to write yourself, or its proprietary, or boring, or so solid no bugs in years. <br /> <br /> The extensions is what sits between the ruby runtime and exposes the funcationality of the Awesome Library to the ruby runtime so that your ruby program can use it. <br /> <br /> <br />
  • have a program <br /> <br /> Need to access some functionality in a third party library, it is either to time consuming to write yourself, or its proprietary, or boring, or so solid no bugs in years. <br /> <br /> The extensions is what sits between the ruby runtime and exposes the funcationality of the Awesome Library to the ruby runtime so that your ruby program can use it. <br /> <br /> <br />
  • have a program <br /> <br /> Need to access some functionality in a third party library, it is either to time consuming to write yourself, or its proprietary, or boring, or so solid no bugs in years. <br /> <br /> The extensions is what sits between the ruby runtime and exposes the funcationality of the Awesome Library to the ruby runtime so that your ruby program can use it. <br /> <br /> <br />
  • Hi resolution timer library for recording performance metrics at the nanosecond resolution. <br /> <br /> To get nanosecond resolution, you need a very specific system call on ever operating system. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Why would you want to take the time to create Java Extensions for use in Jruby? <br /> <br /> You can already easily utilize all the available Java libraries directly. <br /> You can make it more ruby-esque by writing a pure ruby wrapper around a Java API, as Thomas has pointed out. <br /> <br /> All in all, I would have to say, you would need a pretty compelling reason to do so. <br />
  • <br />
  • Hi resolution timer library for recording performance metrics at the nanosecond resolution. <br /> <br /> To get nanosecond resolution, you need a very specific system call on ever operating system. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • The initial require is the same <br /> but in JRuby, the hook leads us down a different path. <br /> JRuby looks for a .jar that is in the load path, and has the same path as the require <br /> Inside that .jar, the last item element of the require is converted from snake_case to ClassCase, and Service is tacked onto the end. <br /> <br /> That class is instantiated and the basicLoad method is called. This is your hook into the runtime. <br /> <br /> See the javadoc for LoadService.java <br />
  • The initial require is the same <br /> but in JRuby, the hook leads us down a different path. <br /> JRuby looks for a .jar that is in the load path, and has the same path as the require <br /> Inside that .jar, the last item element of the require is converted from snake_case to ClassCase, and Service is tacked onto the end. <br /> <br /> That class is instantiated and the basicLoad method is called. This is your hook into the runtime. <br /> <br /> See the javadoc for LoadService.java <br />
  • The initial require is the same <br /> but in JRuby, the hook leads us down a different path. <br /> JRuby looks for a .jar that is in the load path, and has the same path as the require <br /> Inside that .jar, the last item element of the require is converted from snake_case to ClassCase, and Service is tacked onto the end. <br /> <br /> That class is instantiated and the basicLoad method is called. This is your hook into the runtime. <br /> <br /> See the javadoc for LoadService.java <br />
  • The initial require is the same <br /> but in JRuby, the hook leads us down a different path. <br /> JRuby looks for a .jar that is in the load path, and has the same path as the require <br /> Inside that .jar, the last item element of the require is converted from snake_case to ClassCase, and Service is tacked onto the end. <br /> <br /> That class is instantiated and the basicLoad method is called. This is your hook into the runtime. <br /> <br /> See the javadoc for LoadService.java <br />
  • <br />
  • <br />
  • <br />
  • 1) Loading <br /> 2) Initialization <br /> 3) Class Hierarchy definition + Allocators <br /> 4) Method definition(s) <br />
  • Tim Felgentreff <br />
  • <br />

Extending JRuby Extending JRuby Presentation Transcript

  • Extending JRuby JRubyConf 2010 Jeremy Hinegardner
  • All Work Collective Intellect
  • All Play github.com/copiousfreetime
  • Dull Boy @copiousfreetime
  • Extensions
  • Ruby Program
  • Ruby Program Some Awesome Library sal.{dll,so,jar}
  • Ruby Program Ruby Runtime Some Awesome Library sal.{dll,so,jar}
  • Ruby Program Ruby Runtime Extension API Some Awesome Library sal.{dll,so,jar}
  • Ruby Program Ruby Runtime Extension Extension API Some Awesome Library sal.{dll,so,jar}
  • Hitimes
  • MRI - C Extensions
  • How Many of You Have ... ... A C Extension
  • How Many of You Have ... USED ... A C Extension
  • How Many of You Have ... USED LOOKED AT THE SOURCE CODE OF ... A C Extension
  • How Many of You Have ... USED LOOKED AT THE SOURCE CODE OF WRITTEN ... A C Extension
  • C Extension Trace
  • C Extension Trace % irb >> require 'rubygems' >> require 'hitimes'
  • C Extension Trace % irb >> require 'rubygems'| grep require % cat lib/hitimes.rb require 'hitimes/paths' >> require 'hitimes' require 'hitimes/version' require "hitimes/#{RUBY_VERSION.sub(/.d$/,'')}/hitimes_ext" ...
  • C Extension Trace % irb >> require 'rubygems'| grep require % cat lib/hitimes.rb require 'hitimes/paths' >> require 'hitimes' require 'hitimes/version' require "hitimes/#{RUBY_VERSION.sub(/.d$/,'')}/hitimes_ext" % find ./lib -type f -name 'hitimes_ext*' ... ./lib/hitimes/1.8/hitimes_ext.bundle ...
  • C Extension Trace % irb >> require 'rubygems'| grep require % cat lib/hitimes.rb require 'hitimes/paths' >> require 'hitimes' require 'hitimes/version' require "hitimes/#{RUBY_VERSION.sub(/.d$/,'')}/hitimes_ext" % find ./lib -type f -name 'hitimes_ext*' ... ./lib/hitimes/1.8/hitimes_ext.bundle ... % cat ext/hitimes/hitimes_ext.c void Init_hitimes_ext( ) { mH = rb_define_module("Hitimes"); eH_Error = rb_define_class_under(mH, "Error", rb_eStandardError); Init_hitimes_interval(); Init_hitimes_stats( ); }
  • void Init_hitimes_interval() { mH = rb_define_module("Hitimes"); cH_Interval = rb_define_class_under( mH, "Interval", rb_cObject ); rb_define_alloc_func( cH_Interval, hitimes_interval_alloc ); rb_define_module_function( cH_Interval, "now", hitimes_interval_now, 0 ); rb_define_module_function( cH_Interval, "measure", hitimes_interval_measure, 0 ); rb_define_method( cH_Interval, "duration", hitimes_interval_duration, 0 ); rb_define_method( cH_Interval, "duration_so_far", hitimes_interval_duration_so_far, 0); rb_define_method( cH_Interval, "started?", hitimes_interval_started, 0 ); rb_define_method( cH_Interval, "running?", hitimes_interval_running, 0 ); rb_define_method( cH_Interval, "stopped?", hitimes_interval_stopped, 0 ); rb_define_method( cH_Interval, "start_instant", hitimes_interval_start_instant, 0 ); rb_define_method( cH_Interval, "stop_instant", hitimes_interval_stop_instant, 0 ); rb_define_method( cH_Interval, "start", hitimes_interval_start, 0); rb_define_method( cH_Interval, "stop", hitimes_interval_stop, 0); rb_define_method( cH_Interval, "split", hitimes_interval_split, 0); }
  • JRuby - Java Extensions
  • _WHY?
  • _Why Not?
  • Hitimes
  • hitimes_instant_t hitimes_get_current_instant() { LARGE_INTEGER tick; QueryPerformanceCounter(&tick); return (hitimes_instant_t)tick.QuadPart; }
  • hitimes_instant_t hitimes_get_current_instant() { LARGE_INTEGER tick; QueryPerformanceCounter(&tick); return (hitimes_instant_t)tick.QuadPart; } hitimes_instant_t hitimes_get_current_instant( ) { Nanoseconds nano = AbsoluteToNanoseconds( UpTime() ); return *( hitimes_instant_t *)&nano; }
  • hitimes_instant_t hitimes_get_current_instant() { LARGE_INTEGER tick; QueryPerformanceCounter(&tick); return (hitimes_instant_t)tick.QuadPart; } hitimes_instant_t hitimes_get_current_instant( ) { Nanoseconds nano = AbsoluteToNanoseconds( UpTime() ); return *( hitimes_instant_t *)&nano; } hitimes_instant_t hitimes_get_current_instant( ) { clock_gettime( CLOCK_MONOTONIC,&time); return ( ( NANOSECONDS_PER_SECOND * (long)time.tv_sec ) + time.tv_nsec ); }
  • ?
  • System.nanoTime()
  • Java Extension Trace
  • Java Extension Trace % irb >> require 'rubygems' >> require 'hitimes'
  • Java Extension Trace % irb lib/hitimes.rb % cat >> require 'rubygems' ... >> require 'hitimes' if RUBY_PLATFORM == "java" then require 'hitimes/hitimes' else ...
  • Java Extension Trace % irb lib/hitimes.rb % cat >> require 'rubygems' ... >> require 'hitimes' if RUBY_PLATFORM == "java" then require 'hitimes/hitimes' else find ./lib -type f -name '*.jar' % ... ./lib/hitimes/hitimes.jar
  • Java Extension Trace % irb lib/hitimes.rb % cat >> require 'rubygems' ... >> require 'hitimes' if RUBY_PLATFORM == "java" then require 'hitimes/hitimes' else find ./lib -type f -name '*.jar' % ... ./lib/hitimes/hitimes.jar % cat ext/java/src/hitimes/HitimesService.java package hitimes; [...] import org.jruby.runtime.load.BasicLibraryService; public class HitimesService implements BasicLibraryService { public boolean basicLoad( final Ruby runtime ) throws IOException { Hitimes.createHitimes( runtime ); return true; } }
  • package hitimes; @JRubyModule( name = "Hitimes" ) public class Hitimes { public static RubyModule createHitimes( Ruby runtime ) { RubyModule mHitimes = runtime.defineModule("Hitimes"); RubyClass cStandardError = runtime.getStandardError(); RubyClass cHitimesError = mHitimes.defineClassUnder("Error", cStandardError, cStandardError.getAllocator()); RubyClass cHitimesStats = mHitimes.defineClassUnder("Stats", runtime.getObject(), HitimesStats.ALLOCATOR ); cHitimesStats.defineAnnotatedMethods( HitimesStats.class ); RubyClass cHitimesInterval = mHitimes.defineClassUnder("Interval", runtime.getObject(), HitimesInterval.ALLOCATOR ); Hitimes.hitimesIntervalClass = cHitimesInterval; cHitimesInterval.defineAnnotatedMethods( HitimesInterval.class ); return mHitimes; } [...] }
  • Annotations @JRubyClass( name = "Hitimes::Interval" ) public class HitimesInterval extends RubyObject { ... @JRubyMethod( name = "duration", alias = { "length", "to_f", "to_seconds" } ) public IRubyObject duration() { ... } @JRubyMethod( name = "started?" ) public IRubyObject is_started() { ... } @JRubyMethod( name = "now", module = true ) public static IRubyObject now( IRubyObject self ) { ... } }
  • Annotations @JRubyClass( name = "Hitimes::Interval" ) public class HitimesInterval extends RubyObject { ... @JRubyMethod( name = "measure", module = true, frame = true ) public static IRubyObject measure( IRubyObject self, Block block ) { Ruby runtime = self.getRuntime(); if ( block.isGiven() ) { IRubyObject nil = runtime.getNil(); ThreadContext context = runtime.getCurrentContext(); [...] interval.start(); block.yield( context, nil ); interval.stop(); return interval.duration(); } else { throw Hitimes.newHitimesError( runtime, "No block given to Interval.measure" ); } } }
  • MRI - C Extension JRuby - Java Extension require ‘hitimes/hitimes_ext require ‘hitimes/hitimes’ lib/hitimes/hitimes_ext.so lib/hitimes/hitimes.jar public class HitimesService implements BasicLibraryService { void Init_hitimes_ext() public boolean basicLoad( ... ) { ... } } mH = rb_define_module("Hitimes"); RubyModule mHitimes = runtime.defineModule("Hitimes"); cH_Interval = rb_define_class_under( mH, "Interval", RubyClass cHitimesInterval = rb_cObject ); mHitimes.defineClassUnder("Interval", rb_define_alloc_func( cH_Interval, hitimes_interval_alloc ); runtime.getObject(), HitimesInterval.ALLOCATOR ); rb_define_module_function( cH_Interval, "measure", cHitimesInterval.defineAnnotatedMethods( HitimesInterval.class ); rb_define_method( cH_Interval,"duration", ... ) rb_define_method( cH_Interval,"started?", ... ) // Combined with the @JRubyMethod( name = ... ) rb_define_method( cH_Interval,"duration", ... ) // Annotations ...
  • JRuby - C Extensions
  • Jeremy Hinegardner @copiousfreetime jeremy@hinegardner.org Thanks! http://copiousfreetime.org http://twitter.com/jruby/team http://github.com/copiousfreetime/hitimes - Hitimes library http://www.serabe.com/ - several blog posts jruby extensions http://ola-bini.blogspot.com/2006/10/jruby-tutorial-4-writing-java.html http://github.com/jruby/jruby/blob/master/src/org/jruby/runtime/load/ LoadService.java http://tatice.deviantart.com/ - Operating System Icons