Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f8fd25888be9^
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2fb31d6d76ea
Choose a head ref
  • 2 commits
  • 9 files changed
  • 1 contributor

Commits on May 10, 2018

  1. Copy the full SHA
    f8fd258 View commit details
  2. Copy the full SHA
    2fb31d6 View commit details
8 changes: 8 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -4819,6 +4819,12 @@ public RubyClass getData() {
return dataClass;
}

/**
* @return Class -> extension initializer map
* @note Internal API, subject to change!
*/
public Map<Class, Consumer<RubyModule>> getJavaExtensionDefinitions() { return javaExtensionDefinitions; }

@Deprecated
private static final RecursiveFunctionEx<RecursiveFunction> LEGACY_RECURSE = new RecursiveFunctionEx<RecursiveFunction>() {
@Override
@@ -5289,6 +5295,8 @@ protected TypePopulator computeValue(Class<?> type) {

private volatile MRIRecursionGuard mriRecursionGuard;

private final Map<Class, Consumer<RubyModule>> javaExtensionDefinitions = new WeakHashMap<>(); // caller-syncs

// For strptime processing we cache the parsed format strings since most applications
// reuse the same formats over and over. This is also unbounded (for now) since all applications
// I know of use very few of them. Even if there are many the size of these lists are modest.
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@
import org.jruby.RubyModule;
import org.jruby.exceptions.RaiseException;
import org.jruby.exceptions.Unrescuable;
import org.jruby.javasupport.ext.JavaExtensions;
import org.jruby.runtime.Helpers;
import org.jruby.util.ArraySupport;
import org.jruby.util.Loader;
@@ -124,7 +125,9 @@ public JavaClass computeValue(Class<?> klass) {
*/
@Override
public synchronized RubyModule computeValue(Class<?> klass) {
return Java.createProxyClassForClass(runtime, klass);
RubyModule proxyKlass = Java.createProxyClassForClass(runtime, klass);
JavaExtensions.define(klass, proxyKlass); // (lazy) load extensions
return proxyKlass;
}
});

38 changes: 38 additions & 0 deletions core/src/main/java/org/jruby/javasupport/ext/JavaExtensions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.jruby.javasupport.ext;

import org.jruby.Ruby;
import org.jruby.RubyModule;

import java.util.Map;
import java.util.WeakHashMap;
import java.util.function.Consumer;

/**
* Lazy Java class extensions initialization.
*
* @note Internal API
* @author kares
*/
public class JavaExtensions {

private static final boolean IMMEDIATE = false;

private JavaExtensions() { /* hidden */ }

static void put(final Ruby runtime, Class javaClass, Consumer<RubyModule> proxyClass) {
if (IMMEDIATE) {
proxyClass.accept( org.jruby.javasupport.Java.getProxyClass(runtime, javaClass) );
return;
}
Object previous = runtime.getJavaExtensionDefinitions().put(javaClass, proxyClass);
assert previous == null;
}

public static void define(final Class javaClass, final RubyModule proxyClass) {
final Ruby runtime = proxyClass.getRuntime();
runtime.getJavaExtensionDefinitions().getOrDefault(javaClass, NOOP).accept(proxyClass);
}

private static final Consumer<RubyModule> NOOP = (noop) -> { /* no extensions */ };

}
18 changes: 9 additions & 9 deletions core/src/main/java/org/jruby/javasupport/ext/JavaIo.java
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@
import org.jruby.RubyIO;
import org.jruby.RubyModule;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.javasupport.Java;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

@@ -47,16 +46,17 @@
public abstract class JavaIo {

public static void define(final Ruby runtime) {
RubyModule proxyClass;
JavaExtensions.put(runtime, java.io.InputStream.class, (proxyClass) -> {
proxyClass.addMethodInternal("to_io", new InputStreamToIO(proxyClass));
});

proxyClass = Java.getProxyClass(runtime, java.io.InputStream.class);
proxyClass.addMethodInternal("to_io", new InputStreamToIO(proxyClass));
JavaExtensions.put(runtime, java.io.OutputStream.class, (proxyClass) -> {
proxyClass.addMethodInternal("to_io", new OutputStreamToIO(proxyClass));
});

proxyClass = Java.getProxyClass(runtime, java.io.OutputStream.class);
proxyClass.addMethodInternal("to_io", new OutputStreamToIO(proxyClass));

proxyClass = Java.getProxyClass(runtime, java.nio.channels.Channel.class);
proxyClass.addMethodInternal("to_io", new ChannelToIO(proxyClass));
JavaExtensions.put(runtime, java.nio.channels.Channel.class, (proxyClass) -> {
proxyClass.addMethodInternal("to_io", new ChannelToIO(proxyClass));
});
}

private static final class InputStreamToIO extends JavaMethod.JavaMethodZeroOrOne {
78 changes: 37 additions & 41 deletions core/src/main/java/org/jruby/javasupport/ext/JavaLang.java
Original file line number Diff line number Diff line change
@@ -59,32 +59,28 @@
public abstract class JavaLang {

public static void define(final Ruby runtime) {
Iterable.define(runtime);
Comparable.define(runtime);
Throwable.define(runtime);
Runnable.define(runtime);
Character.define(runtime);
Number.define(runtime);
Class.define(runtime);
ClassLoader.define(runtime);
JavaExtensions.put(runtime, java.lang.Iterable.class, (proxyClass) -> Iterable.define(runtime, proxyClass));
JavaExtensions.put(runtime, java.lang.Comparable.class, (proxyClass) -> Comparable.define(runtime, proxyClass));
JavaExtensions.put(runtime, java.lang.Throwable.class, (proxyClass) -> Throwable.define(runtime, (RubyClass) proxyClass));
JavaExtensions.put(runtime, java.lang.Runnable.class, (proxyClass) -> Runnable.define(runtime, proxyClass));
JavaExtensions.put(runtime, java.lang.Character.class, (proxyClass) -> Character.define(runtime, (RubyClass) proxyClass));
JavaExtensions.put(runtime, java.lang.Number.class, (proxyClass) -> Number.define(runtime, (RubyClass) proxyClass));
JavaExtensions.put(runtime, java.lang.Class.class, (proxyClass) -> Class.define(runtime, (RubyClass) proxyClass));
JavaExtensions.put(runtime, java.lang.ClassLoader.class, (proxyClass) -> ClassLoader.define(runtime, (RubyClass) proxyClass));
// Java::byte[].class_eval ...
final RubyModule byteArray = Java.getProxyClass(runtime, new byte[0].getClass());
byteArray.addMethod("ubyte_get", new UByteGet(byteArray));
byteArray.addMethod("ubyte_set", new UByteSet(byteArray));

final RubyModule String = Java.getProxyClass(runtime, java.lang.String.class);
String.defineAlias("to_str", "to_s");

final RubyModule Number = Java.getProxyClass(runtime, java.lang.Number.class);
Number.defineAlias("to_int", "longValue");
Number.defineAlias("to_f", "doubleValue");
JavaExtensions.put(runtime, new byte[0].getClass(), (byteArray) -> {
byteArray.addMethod("ubyte_get", new UByteGet(byteArray));
byteArray.addMethod("ubyte_set", new UByteSet(byteArray));
});
JavaExtensions.put(runtime, java.lang.String.class, (proxyClass) -> {
proxyClass.defineAlias("to_str", "to_s");
});
}

@JRubyModule(name = "Java::JavaLang::Iterable", include = "Enumerable")
public static class Iterable {

static RubyModule define(final Ruby runtime) {
final RubyModule Iterable = Java.getProxyClass(runtime, java.lang.Iterable.class);
static RubyModule define(final Ruby runtime, final RubyModule Iterable) {
Iterable.includeModule( runtime.getEnumerable() ); // include Enumerable
Iterable.defineAnnotatedMethods(Iterable.class);
return Iterable;
@@ -181,8 +177,7 @@ public static IRubyObject count(final ThreadContext context, final IRubyObject s
@JRubyClass(name = "Java::JavaLang::Comparable", include = "Comparable")
public static class Comparable {

static RubyModule define(final Ruby runtime) {
final RubyModule Comparable = Java.getProxyClass(runtime, java.lang.Comparable.class);
static RubyModule define(final Ruby runtime, final RubyModule Comparable) {
Comparable.includeModule( runtime.getComparable() ); // include Comparable
Comparable.defineAnnotatedMethods(Comparable.class);
return Comparable;
@@ -210,8 +205,7 @@ public static IRubyObject cmp(final ThreadContext context, final IRubyObject sel
@JRubyClass(name = "Java::JavaLang::Throwable")
public static class Throwable {

static RubyModule define(final Ruby runtime) {
final RubyModule Throwable = Java.getProxyClass(runtime, java.lang.Throwable.class);
static RubyModule define(final Ruby runtime, final RubyClass Throwable) {
Throwable.defineAnnotatedMethods(Throwable.class);
return Throwable;
}
@@ -279,8 +273,7 @@ private static boolean checkNativeException(IRubyObject self, IRubyObject other)
@JRubyModule(name = "Java::JavaLang::Runnable")
public static class Runnable {

static RubyModule define(final Ruby runtime) {
final RubyModule Runnable = Java.getProxyClass(runtime, java.lang.Runnable.class);
static RubyModule define(final Ruby runtime, final RubyModule Runnable) {
Runnable.defineAnnotatedMethods(Runnable.class);
return Runnable;
}
@@ -328,10 +321,13 @@ protected final IRubyObject doYield(ThreadContext context, Block block, IRubyObj
@JRubyClass(name = "Java::JavaLang::Number")
public static class Number {

static RubyClass define(final Ruby runtime) {
final RubyModule Number = Java.getProxyClass(runtime, java.lang.Number.class);
static RubyClass define(final Ruby runtime, final RubyClass Number) {
Number.defineAnnotatedMethods(Number.class);
return (RubyClass) Number;

Number.defineAlias("to_int", "longValue");
Number.defineAlias("to_f", "doubleValue");

return Number;
}

@JRubyMethod(name = "to_f")
@@ -409,24 +405,26 @@ public static IRubyObject coerce(final ThreadContext context, final IRubyObject
@JRubyClass(name = "Java::JavaLang::Character")
public static class Character {

static RubyClass define(final Ruby runtime) {
final RubyModule Character = Java.getProxyClass(runtime, java.lang.Character.class);
static RubyClass define(final Ruby runtime, final RubyClass Character) {
System.out.println("defining Character extensions: proxy-class: " + Character);
Character.defineAnnotatedMethods(Character.class);
return (RubyClass) Character;
}

@JRubyMethod(name = "java_identifier_start?", meta = true)
public static IRubyObject java_identifier_start_p(final IRubyObject self, final IRubyObject num) {
return self.getRuntime().newBoolean( java.lang.Character.isJavaIdentifierStart(to_char(num)) );
public static IRubyObject java_identifier_start_p(final ThreadContext context, final IRubyObject self,
final IRubyObject num) {
return context.runtime.newBoolean( java.lang.Character.isJavaIdentifierStart(int_char(num)) );
}

@JRubyMethod(name = "java_identifier_part?", meta = true)
public static IRubyObject java_identifier_part_p(final IRubyObject self, final IRubyObject num) {
return self.getRuntime().newBoolean( java.lang.Character.isJavaIdentifierPart(to_char(num)) );
public static IRubyObject java_identifier_part_p(final ThreadContext context, final IRubyObject self,
final IRubyObject num) {
return context.runtime.newBoolean( java.lang.Character.isJavaIdentifierPart(int_char(num)) );
}

private static char to_char(final IRubyObject num) {
return (java.lang.Character) num.toJava(java.lang.Character.TYPE);
private static int int_char(IRubyObject num) { // str.ord -> Fixnum
return num.toJava(java.lang.Character.TYPE);
}

@JRubyMethod(name = "to_i")
@@ -440,8 +438,7 @@ public static IRubyObject to_i(final ThreadContext context, final IRubyObject se
@JRubyClass(name = "Java::JavaLang::Class")
public static class Class {

static RubyClass define(final Ruby runtime) {
final RubyModule Class = Java.getProxyClass(runtime, java.lang.Class.class);
static RubyClass define(final Ruby runtime, final RubyClass Class) {
Class.includeModule( runtime.getComparable() ); // include Comparable
Class.defineAnnotatedMethods(Class.class);
return (RubyClass) Class;
@@ -602,8 +599,7 @@ public static IRubyObject static_p(final IRubyObject self) {
@JRubyClass(name = "Java::JavaLang::ClassLoader")
public static class ClassLoader {

static RubyModule define(final Ruby runtime) {
final RubyModule ClassLoader = Java.getProxyClass(runtime, java.lang.ClassLoader.class);
static RubyModule define(final Ruby runtime, final RubyClass ClassLoader) {
ClassLoader.defineAnnotatedMethods(ClassLoader.class);
return ClassLoader;
}
16 changes: 6 additions & 10 deletions core/src/main/java/org/jruby/javasupport/ext/JavaLangReflect.java
Original file line number Diff line number Diff line change
@@ -31,7 +31,6 @@
import org.jruby.*;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.javasupport.Java;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@@ -50,16 +49,15 @@
public abstract class JavaLangReflect {

public static void define(final Ruby runtime) {
Constructor.define(runtime);
Field.define(runtime);
Method.define(runtime);
JavaExtensions.put(runtime, java.lang.reflect.Constructor.class, (proxyClass) -> Constructor.define(runtime, (RubyClass) proxyClass));
JavaExtensions.put(runtime, java.lang.reflect.Field.class, (proxyClass) -> Field.define(runtime, (RubyClass) proxyClass));
JavaExtensions.put(runtime, java.lang.reflect.Method.class, (proxyClass) -> Method.define(runtime, (RubyClass) proxyClass));
}

@JRubyClass(name = "Java::JavaLangReflect::Constructor")
public static class Constructor {

static RubyClass define(final Ruby runtime) {
final RubyModule Constructor = Java.getProxyClass(runtime, java.lang.reflect.Constructor.class);
static RubyClass define(final Ruby runtime, final RubyClass Constructor) {
Constructor.defineAnnotatedMethods(Constructor.class);
return (RubyClass) Constructor;
}
@@ -120,8 +118,7 @@ public static IRubyObject static_p(final IRubyObject self) {
@JRubyClass(name = "Java::JavaLangReflect::Method")
public static class Method {

static RubyClass define(final Ruby runtime) {
final RubyModule Method = Java.getProxyClass(runtime, java.lang.reflect.Method.class);
static RubyClass define(final Ruby runtime, final RubyClass Method) {
Method.defineAnnotatedMethods(Method.class);
return (RubyClass) Method;
}
@@ -201,8 +198,7 @@ public static IRubyObject static_p(final IRubyObject self) {
@JRubyClass(name = "Java::JavaLangReflect::Field")
public static class Field {

static RubyClass define(final Ruby runtime) {
final RubyModule Field = Java.getProxyClass(runtime, java.lang.reflect.Field.class);
static RubyClass define(final Ruby runtime, final RubyClass Field) {
Field.defineAnnotatedMethods(Field.class);
return (RubyClass) Field;
}
8 changes: 3 additions & 5 deletions core/src/main/java/org/jruby/javasupport/ext/JavaNet.java
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@
import org.jruby.RubyIO;
import org.jruby.RubyModule;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.javasupport.Java;
import org.jruby.runtime.Block;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
@@ -52,10 +51,9 @@
public abstract class JavaNet {

public static void define(final Ruby runtime) {
RubyModule proxyClass;

proxyClass = Java.getProxyClass(runtime, java.net.URL.class);
proxyClass.addMethodInternal("open", new URLOpenMethod(proxyClass));
JavaExtensions.put(runtime, java.net.URL.class, (proxyClass) -> {
proxyClass.addMethodInternal("open", new URLOpenMethod(proxyClass));
});
}

private static final class URLOpenMethod extends JavaMethod.JavaMethodZeroOrNBlock {
24 changes: 8 additions & 16 deletions core/src/main/java/org/jruby/javasupport/ext/JavaUtil.java
Original file line number Diff line number Diff line change
@@ -60,18 +60,16 @@
public abstract class JavaUtil {

public static void define(final Ruby runtime) {
Enumeration.define(runtime);
Iterator.define(runtime);
Collection.define(runtime);
List.define(runtime);
JavaExtensions.put(runtime, java.util.Enumeration.class, (proxyClass) -> Enumeration.define(runtime, proxyClass));
JavaExtensions.put(runtime, java.util.Iterator.class, (proxyClass) -> Iterator.define(runtime, proxyClass));
JavaExtensions.put(runtime, java.util.Collection.class, (proxyClass) -> Collection.define(runtime, proxyClass));
JavaExtensions.put(runtime, java.util.List.class, (proxyClass) -> List.define(runtime, proxyClass));
}

@JRubyModule(name = "Java::JavaUtil::Enumeration", include = "Enumerable")
public static class Enumeration {

static RubyModule define(final Ruby runtime) {
final RubyModule Enumeration = //Java.getProxyClass(runtime, java.util.Enumeration.class);
JavaClass.get(runtime, java.util.Enumeration.class).getProxyModule();
static RubyModule define(final Ruby runtime, final RubyModule Enumeration) {
Enumeration.includeModule( runtime.getEnumerable() ); // include Enumerable
Enumeration.defineAnnotatedMethods(Enumeration.class);
return Enumeration;
@@ -93,9 +91,7 @@ public static IRubyObject each(final ThreadContext context, final IRubyObject se
@JRubyModule(name = "Java::JavaUtil::Iterator", include = "Enumerable")
public static class Iterator {

static RubyModule define(final Ruby runtime) {
final RubyModule Iterator = //Java.getProxyClass(runtime, java.util.Iterator.class);
JavaClass.get(runtime, java.util.Iterator.class).getProxyModule();
static RubyModule define(final Ruby runtime, final RubyModule Iterator) {
Iterator.includeModule( runtime.getEnumerable() ); // include Enumerable
Iterator.defineAnnotatedMethods(Iterator.class);
return Iterator;
@@ -117,9 +113,7 @@ public static IRubyObject each(final ThreadContext context, final IRubyObject se
@JRubyModule(name = "Java::JavaUtil::Collection", include = "Enumerable")
public static class Collection {

static RubyModule define(final Ruby runtime) {
final RubyModule Collection = //Java.getProxyClass(runtime, java.util.Collection.class);
JavaClass.get(runtime, java.util.Collection.class).getProxyModule();
static RubyModule define(final Ruby runtime, final RubyModule Collection) {
Collection.includeModule( runtime.getEnumerable() ); // include Enumerable
Collection.defineAnnotatedMethods(Collection.class);
return Collection;
@@ -262,9 +256,7 @@ public static IRubyObject join(final ThreadContext context, final IRubyObject se
@JRubyModule(name = "Java::JavaUtil::List")
public static class List {

static RubyModule define(final Ruby runtime) {
final RubyModule List = //Java.getProxyClass(runtime, java.util.List.class);
JavaClass.get(runtime, java.util.List.class).getProxyModule();
static RubyModule define(final Ruby runtime, final RubyModule List) {
List.defineAnnotatedMethods(List.class);
return List;
}
Loading