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: b95321137df6
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4347dd45d6a1
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 25, 2014

  1. Fix indentation.

    headius committed Nov 25, 2014
    Copy the full SHA
    bbdbe6f View commit details
  2. Avoid CNFE by setting classloader resource of service .class.

    When loading a .jar file, JRuby will also attempt to load a class
    named *Service based on the require path of the jar, in order to
    boot the extension the jar contains (if present). However this
    usually fails, since requiring a jar is also the preferred way to
    make a jar's contents available. As a result, every jar loaded by
    a JRuby application triggers the *Service search, which usually
    results in a ClassNotFoundException. Exceptions are expensive, so
    this commit tries to actively look for the *Service.class rather
    than falling into the heavier failure logic.
    headius committed Nov 25, 2014
    Copy the full SHA
    2e2924c View commit details
  3. Copy the full SHA
    4347dd4 View commit details
Showing with 38 additions and 29 deletions.
  1. +36 −28 core/src/main/java/org/jruby/runtime/load/ClassExtensionLibrary.java
  2. +2 −1 core/src/test/java/org/jruby/test/MainTestSuite.java
Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@

import org.jruby.Ruby;

import java.net.URL;

/**
* The ClassExtensionLibrary wraps a class which implements BasicLibraryService,
* and when asked to load the service, does a basicLoad of the BasicLibraryService.
@@ -42,39 +44,45 @@ public class ClassExtensionLibrary implements Library {
private final String name;

static ClassExtensionLibrary tryFind(Ruby runtime, String searchName) {
// Create package name, by splitting on / and joining all but the last elements with a ".", and downcasing them.
String[] all = searchName.split("/");

StringBuilder finName = new StringBuilder();
for(int i=0, j=(all.length-1); i<j; i++) {
finName.append(all[i].toLowerCase()).append(".");
}
// Create package name, by splitting on / and joining all but the last elements with a ".", and downcasing them.
String[] all = searchName.split("/");

try {
// Make the class name look nice, by splitting on _ and capitalize each segment, then joining
// the, together without anything separating them, and last put on "Service" at the end.
String[] last = all[all.length-1].split("_");
for(int i=0, j=last.length; i<j; i++) {
if ("".equals(last[i])) break;
finName.append(Character.toUpperCase(last[i].charAt(0))).append(last[i].substring(1));
StringBuilder finName = new StringBuilder();
for (int i = 0, j = (all.length - 1); i < j; i++) {
finName.append(all[i].toLowerCase()).append(".");
}
finName.append("Service");

// We don't want a package name beginning with dots, so we remove them
String className = finName.toString().replaceAll("^\\.*","");
try {
// Make the class name look nice, by splitting on _ and capitalize each segment, then joining
// the, together without anything separating them, and last put on "Service" at the end.
String[] last = all[all.length - 1].split("_");
for (int i = 0, j = last.length; i < j; i++) {
if ("".equals(last[i])) break;
finName.append(Character.toUpperCase(last[i].charAt(0))).append(last[i].substring(1));
}
finName.append("Service");

// quietly try to load the class
Class theClass = runtime.getJavaSupport().loadJavaClass(className);
return new ClassExtensionLibrary(className + ".java", theClass);
} catch (ClassNotFoundException cnfe) {
if (runtime.isDebug()) cnfe.printStackTrace();
// We don't want a package name beginning with dots, so we remove them
String className = finName.toString().replaceAll("^\\.*", "");
String classFile = className.replaceAll("\\.", "/") + ".class";

// So apparently the class doesn't exist
return null;
} catch (UnsupportedClassVersionError ucve) {
if (runtime.isDebug()) ucve.printStackTrace();
throw runtime.newLoadError("JRuby ext built for wrong Java version in `" + finName + "': " + ucve, finName.toString());
}
// quietly try to load the class, which must be reachable as a .class resource
URL resource = runtime.getJRubyClassLoader().getResource(classFile);
if (resource != null) {
Class theClass = runtime.getJavaSupport().loadJavaClass(className);
return new ClassExtensionLibrary(className + ".java", theClass);
}

return null;
} catch (ClassNotFoundException cnfe) {
if (runtime.isDebug()) cnfe.printStackTrace();

// So apparently the class doesn't exist
return null;
} catch (UnsupportedClassVersionError ucve) {
if (runtime.isDebug()) ucve.printStackTrace();
throw runtime.newLoadError("JRuby ext built for wrong Java version in `" + finName + "': " + ucve, finName.toString());
}
}

public ClassExtensionLibrary(String name, Class extension) {
3 changes: 2 additions & 1 deletion core/src/test/java/org/jruby/test/MainTestSuite.java
Original file line number Diff line number Diff line change
@@ -95,7 +95,8 @@ public static Test suite() throws Throwable {
suite.addTestSuite(ParameterizedWriterTest.class);
suite.addTestSuite(TestRubyRational.class);
suite.addTestSuite(TestRecursiveCheck.class);
suite.addTestSuite(TestRegexpCache.class);
// Disabled test due to difficulty of making WeakRef logic deterministic
// suite.addTestSuite(TestRegexpCache.class);
return suite;
}
}