Skip to content

Commit

Permalink
Merge pull request jruby#7332 from ccutrer/reified_parent_not_in_syst…
Browse files Browse the repository at this point in the history
…em_classloader

defined reified classes with their parent class's classloader as parent
  • Loading branch information
headius authored Sep 12, 2022
2 parents 489cd92 + d7a87d4 commit 14fa2b5
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 1 deletion.
8 changes: 7 additions & 1 deletion core/src/main/java/org/jruby/RubyClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import org.jruby.compiler.impl.SkinnyMethodAdapter;
import org.jruby.exceptions.RaiseException;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.java.codegen.MultiClassLoader;
import org.jruby.java.codegen.RealClassGenerator;
import org.jruby.java.codegen.Reified;
import org.jruby.java.proxies.ConcreteJavaProxy;
Expand Down Expand Up @@ -90,6 +91,7 @@
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.CodegenUtils;
import org.jruby.util.JavaNameMangler;
import org.jruby.util.Loader;
import org.jruby.util.OneShotClassLoader;
import org.jruby.util.StringSupport;
import org.jruby.util.collections.ConcurrentWeakHashMap;
Expand Down Expand Up @@ -1357,7 +1359,11 @@ public synchronized void reify(String classDumpDir, boolean useChildLoader) {
parentCL = (OneShotClassLoader) parentReified.getClassLoader();
} else {
if (useChildLoader) {
parentCL = new OneShotClassLoader(runtime.getJRubyClassLoader());
MultiClassLoader parentLoader = new MultiClassLoader(runtime.getJRubyClassLoader());
for(Loader cLoader : runtime.getInstanceConfig().getExtraLoaders()) {
parentLoader.addClassLoader(cLoader.getClassLoader());
}
parentCL = new OneShotClassLoader(parentLoader);
} else {
parentCL = runtime.getJRubyClassLoader();
}
Expand Down
10 changes: 10 additions & 0 deletions rakelib/test.rake
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,21 @@ namespace :test do
desc "Compile test code"
task :compile do
mkdir_p "test/target/test-classes"
mkdir_p "test/target/test-classes-isolated/java_integration/fixtures/isolated"
mkdir_p "test/target/test-interfaces-isolated/java_integration/fixtures/isolated"

classpath = %w[lib/jruby.jar test/target/junit.jar test/target/annotation-api.jar].join(File::PATH_SEPARATOR)
# try detecting javac - so we use the same Java versions as we're running (JAVA_HOME) with :
java_home = [ ENV_JAVA['java.home'], File.join(ENV_JAVA['java.home'], '..') ] # in case of jdk/jre
javac = java_home.map { |home| File.expand_path('bin/javac', home) }.find { |javac| File.exist?(javac) } || 'javac'
sh "#{javac} -cp #{classpath} -d test/target/test-classes #{Dir['spec/java_integration/fixtures/**/*.java'].to_a.join(' ')}"
# move the objects that need to be in separate class loaders
mv "test/target/test-classes/java_integration/fixtures/isolated/classes",
"test/target/test-classes-isolated/java_integration/fixtures/isolated",
force: true
mv "test/target/test-classes/java_integration/fixtures/isolated/interfaces",
"test/target/test-interfaces-isolated/java_integration/fixtures/isolated",
force: true
end

short_tests = ['jruby', 'mri']
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package java_integration.fixtures.isolated.classes;

public class GH7327Base {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package java_integration.fixtures.isolated.interfaces;

public interface GH7327Interface {
}
31 changes: 31 additions & 0 deletions spec/java_integration/reify/become_java_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,37 @@ class JRUBY5564; end
expect(klass.load_class(a_class.get_name)).to eq(a_class)
end

it "supports reifying concrete classes extending classes from an unrelated class loader" do
isolated_class_path = File.expand_path('../../../../test/target/test-classes-isolated', __FILE__)
classloader = java.net.URLClassLoader.new([java.net.URL.new("file://#{isolated_class_path}/")].to_java(java.net.URL))
JRuby.runtime.instance_config.add_loader(classloader)

# we can reference it from JRuby, because it was added to the JRuby loader above
class GH7327 < Java::Java_integrationFixturesIsolatedClasses::GH7327Base; end
# it should have created a unique Java class
expect(GH7327.become_java!).not_to eq(Java::Java_integrationFixturesIsolatedClasses::GH7327Base.java_class)
ensure
JRuby.runtime.instance_config.extra_loaders.clear
end

it "supports reifying concrete classes extending classes and implementing interfaces from multiple unrelated class loaders" do
isolated_class_path = File.expand_path('../../../../test/target/test-classes-isolated', __FILE__)
classloader1 = java.net.URLClassLoader.new([java.net.URL.new("file://#{isolated_class_path}/")].to_java(java.net.URL))
JRuby.runtime.instance_config.add_loader(classloader1)
isolated_interface_path = File.expand_path('../../../../test/target/test-interfaces-isolated', __FILE__)
classloader2 = java.net.URLClassLoader.new([java.net.URL.new("file://#{isolated_interface_path}/")].to_java(java.net.URL))
JRuby.runtime.instance_config.add_loader(classloader2)

# we can reference them from JRuby, because they were added to the JRuby loader above
class GH7327WithInterface < Java::Java_integrationFixturesIsolatedClasses::GH7327Base
include Java::Java_integrationFixturesIsolatedInterfaces::GH7327Interface
end
# it should have created a unique Java class
expect(GH7327WithInterface.become_java!).not_to eq(Java::Java_integrationFixturesIsolatedClasses::GH7327Base.java_class)
ensure
JRuby.runtime.instance_config.extra_loaders.clear
end

class ReifiedSample
def hello; 'Sayonara from Ruby' end
java_signature "java.lang.String ahoy()"
Expand Down

0 comments on commit 14fa2b5

Please sign in to comment.