Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby & JVM: A (JRuby) Love Story

Ruby & JVM: A (JRuby) Love Story

Yarden Laifenfeld

October 17, 2022
Tweet

More Decks by Yarden Laifenfeld

Other Decks in Programming

Transcript

  1. Ruby & JVM:
    A (Jruby) Love Story
    Yarden Laifenfeld
    @yardenlaif

    View full-size slide

  2. 2
    Who Am I?
    • Software Engineer at Rookout
    • Background in low level C
    programming in linux IOT
    environments
    • Ruby, Java, Go
    • C#, Python, JavaScript, C++

    View full-size slide

  3. What is JRuby?
    3
    “ JRuby is a 100% Java implementation of
    the Ruby programming language. It is Ruby
    for the JVM. ”
    - the JRuby wiki

    View full-size slide

  4. 4
    Should you use JRuby?

    View full-size slide

  5. JRuby Advantages
    5
    ● Integration with Java libraries
    ● Running atop the JVM
    ○ Threads
    ○ Long running applications

    View full-size slide

  6. Why JRuby.md - Jordan Sissel, 2010
    https://gist.github.com/jordansissel/978956
    6
    ● core and stdlib ruby changes violently and without notice and
    without backwards compatibility. I want nothing of that.
    ● need a cross-ruby date library that isn't part of stdlib (see
    previous point) and is also good.
    ● need an easy way to use multiple cpus that is cross-ruby
    (threads are not it)

    View full-size slide

  7. CRuby Advantages
    7
    ● Larger community
    ● More features

    View full-size slide

  8. 8
    Should you use JRuby?
    I don’t know, you choose.

    View full-size slide

  9. Supporting JRuby in one of
    Rookout’s debuggers
    9

    View full-size slide

  10. Supporting JRuby
    10
    ❏ Running an app
    ❏ Adding a breakpoint
    ❏ Collecting data

    View full-size slide

  11. Decision Time
    11
    Java or Ruby

    View full-size slide

  12. Decision Time
    12
    Java or Ruby

    View full-size slide

  13. Running an app
    13
    ● rails server -p 8080 -e development

    View full-size slide

  14. Running an app
    14
    rvm install jruby
    rvm use jruby
    bundle install

    View full-size slide

  15. Running an app
    15

    View full-size slide

  16. Running an app
    16
    3 business days
    later…

    View full-size slide

  17. Running an app
    17
    bundle config unset force_ruby_platform

    View full-size slide

  18. Running an app
    18
    ➜ tutorial-ruby git:(master) ✗ jruby -S rails server -p 8080 -e development
    => Booting Puma
    => Rails 6.0.3.4 application starting in development
    => Run `rails server --help` for more startup options
    Puma starting in single mode...
    * Version 4.3.7 (jruby 9.2.9.0 - ruby 2.5.7), codename: Mysterious Traveller
    * Min threads: 5, max threads: 5
    * Environment: development
    * Listening on tcp://[::1]:8080
    * Listening on tcp://127.0.0.1:8080
    Use Ctrl-C to stop

    View full-size slide

  19. Running an app
    19
    ➜ tutorial-ruby git:(master) ✗ jruby -S rails server -p 8080 -e development
    => Booting Puma
    => Rails 6.0.3.4 application starting in development
    => Run `rails server --help` for more startup options
    Puma starting in single mode...
    * Version 4.3.7 (jruby 9.2.9.0 - ruby 2.5.7), codename: Mysterious Traveller
    * Min threads: 5, max threads: 5
    * Environment: development
    * Listening on tcp://[::1]:8080
    * Listening on tcp://127.0.0.1:8080
    Use Ctrl-C to stop

    View full-size slide

  20. Running an app
    20
    ➜ tutorial-ruby git:(master) ✗ jruby -S rails server -p 8080 -e development
    => Booting Puma
    => Rails 6.0.3.4 application starting in development
    => Run `rails server --help` for more startup options
    Puma starting in single mode...
    * Version 4.3.7 (jruby 9.2.9.0 - ruby 2.5.7), codename: Mysterious Traveller
    * Min threads: 5, max threads: 5
    * Environment: development
    * Listening on tcp://[::1]:8080
    * Listening on tcp://127.0.0.1:8080
    Use Ctrl-C to stop

    View full-size slide

  21. Supporting JRuby
    21
    ? Running an app
    ❏ Adding a breakpoint
    ❏ Collecting data

    View full-size slide

  22. Running an app
    22
    ● bundle add rookout
    ● require 'rookout'
    ::Rookout.start

    View full-size slide

  23. Running an app
    23
    ➜ tutorial-ruby git:(master) ✗ jruby -S rails server -p 8080 -e
    development

    View full-size slide

  24. Running an app
    24
    ➜ tutorial-ruby git:(master) ✗ jruby -S rails server -p 8080 -e
    development
    [Rookout] Successfully connected to controller.

    View full-size slide

  25. Running an app
    25
    ➜ tutorial-ruby git:(master) ✗ jruby -S rails server -p 8080 -e development
    [Rookout] Successfully connected to controller.
    => Booting Puma
    => Rails 6.0.6 application starting in development
    => Run `rails server --help` for more startup options
    Puma starting in single mode...
    * Version 4.3.12 (jruby 9.3.8.0 - ruby 2.6.8), codename: Mysterious Traveller
    * Min threads: 5, max threads: 5
    * Environment: development
    * Listening on tcp://[::1]:8080
    * Listening on tcp://127.0.0.1:8080
    Use Ctrl-C to stop

    View full-size slide

  26. Supporting JRuby
    26
    ✓ Running an app
    ❏ Adding a breakpoint
    ❏ Collecting data

    View full-size slide

  27. TracePoints
    27

    View full-size slide

  28. TracePoints
    28
    tracepoint = Tracepoint.new(:line) do
    ...
    end

    View full-size slide

  29. TracePoints
    29
    tracepoint = Tracepoint.new(:line) do
    ...
    end
    tracepoint.enable

    View full-size slide

  30. TracePoints
    30
    tracepoint = Tracepoint.new(:line) do
    ...
    end
    tracepoint.enable(target: method(:m1),
    target_line: 14)

    View full-size slide

  31. TracePoints in JRuby
    31

    View full-size slide

  32. Workaround
    32
    tracepoint.enable

    View full-size slide

  33. Supporting JRuby
    33
    ✓ Running an app
    ✗ Adding a breakpoint
    ❏ Collecting data

    View full-size slide

  34. Decision Time
    34
    Java or Ruby

    View full-size slide

  35. Decision Time
    35
    Java or Ruby

    View full-size slide

  36. Supporting JRuby
    36
    ❏ Running an app
    ❏ Adding a breakpoint
    ❏ Collecting data

    View full-size slide

  37. Running an app - Java Agents
    37
    ● -javaagent flag
    ● premain entrypoint
    ● Instrumentation API
    App
    JavaAgent
    Instrumentation API

    View full-size slide

  38. Running an app
    38
    ➜ tutorial-ruby git:(master) ✗ jruby -J-javaagent:rook.jar -S rails
    server -p 8080 -e development

    View full-size slide

  39. Running an app
    39
    ➜ tutorial-ruby git:(master) ✗ jruby -J-javaagent:rook.jar -S rails
    server -p 8080 -e development
    [Rookout] Successfully connected to controller.

    View full-size slide

  40. Running an app
    40
    ➜ tutorial-ruby git:(master) ✗ jruby -J-javaagent:rook.jar -S rails server -p 8080 -e
    development
    [Rookout] Successfully connected to controller.
    => Booting Puma
    => Rails 6.0.6 application starting in development
    => Run `rails server --help` for more startup options
    Puma starting in single mode...
    * Version 4.3.12 (jruby 9.3.8.0 - ruby 2.6.8), codename: Mysterious Traveller
    * Min threads: 5, max threads: 5
    * Environment: development
    * Listening on tcp://[::1]:8080
    * Listening on tcp://127.0.0.1:8080
    Use Ctrl-C to stop

    View full-size slide

  41. Supporting JRuby
    41
    ✓ Running an app
    ❏ Adding a breakpoint
    ❏ Collecting data

    View full-size slide

  42. Adding a breakpoint - Class Loaders
    42
    JVM
    Compiler
    Code Bytecode

    View full-size slide

  43. Adding a breakpoint - Class Loaders
    43
    JVM
    32 | …
    33 | new Item()
    34 | …
    Class
    Loader
    Get Item
    class bytecode
    Return Item
    class bytecode

    View full-size slide

  44. Adding a breakpoint - Class Loaders
    44
    JVM
    32 | …
    33 | new Item()
    34 | …
    Class Loader
    Get Item class
    bytecode
    Return Item
    class bytecode
    Class
    Transformer
    Return
    transformed Item
    class bytecode

    View full-size slide

  45. Adding a breakpoint
    45
    Expectation: Works straight away!
    Reality: Doesn’t work at all.

    View full-size slide

  46. 53
    A few, spaced out invocations
    Many, rapid invocations
    Class isn’t loaded
    Class is loaded

    View full-size slide

  47. 54
    A few, spaced out invocations
    Many, rapid invocations
    Class isn’t loaded
    Class is loaded
    JIT

    View full-size slide

  48. JRuby Compilation Modes
    55
    ● Interpretation
    ● JIT
    ● Compilation

    View full-size slide

  49. JRuby Compilation Modes
    56
    compile.mode=FORCE

    View full-size slide

  50. Supporting JRuby
    60
    ✓ Running an app
    ✓ Adding a breakpoint
    ❏ Collecting data

    View full-size slide

  51. Collecting data
    61
    class TasksController
    def create
    params.require(:task).permit(:task)
    task = Task.new(params[:task][:title])
    $tasks_storage.push(task)
    redirect_back(fallback_location: 'tasks')
    end
    end

    View full-size slide

  52. Collecting data
    62
    class TasksController
    def create
    params.require(:task).permit(:task)
    task = Task.new(params[:task][:title])
    $tasks_storage.push(task)
    redirect_back(fallback_location: 'tasks')
    end
    end

    View full-size slide

  53. Collecting data
    63
    class TasksController
    def create
    params.require(:task).permit(:task)
    task = Task.new(params[:task][:title])
    $tasks_storage.push(task)
    redirect_back(fallback_location: 'tasks')
    end
    end

    View full-size slide

  54. Collecting data
    64

    View full-size slide

  55. Collecting data - self
    65

    View full-size slide

  56. Collecting data - locals
    66

    View full-size slide

  57. Supporting JRuby
    67
    ✓ Running an app
    ✓ Adding a breakpoint
    ✓ Collecting data

    View full-size slide

  58. What Next?
    68
    ● Ruby TracePoint API
    ● Java Agents
    ● Class Loaders
    @yardenlaif

    View full-size slide

  59. Thank You!
    @yardenlaif
    69

    View full-size slide