Scala Script Engine creating another instance of a singleton - java

So, I'm creating a scripting system using JSR 223 for Scala, but I came across this problem I can't find any cause for.
There is a singleton-like class, which has methods to add event listeners (from the scripts) and dispatch events (from the core). Everything worked fine, but for some reason the added listeners had disappeared when I got to dispatch an event.
After reproducing the problem, I found out that the script engine creates another instance of the singleton:
Here is my Singleton class:
package test;
import java.util.Arrays;
public final class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
Arrays.stream(Thread.currentThread().getStackTrace()).forEach(System.out::println);
System.out.println();
}
public static Singleton instance() {
return instance;
}
}
And here is my Main class:
package test;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public final class Main {
public static void main(String[] args) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("scala");
// this is a trick I found to access the classpath,
// might be the problem
#SuppressWarnings("rawtypes")
scala.collection.immutable.List nil = scala.collection.immutable.Nil$.MODULE$;
#SuppressWarnings("unchecked")
scala.collection.immutable.$colon$colon<String> vals = scala.collection.immutable.$colon$colon$.MODULE$.apply("true", nil);
((scala.tools.nsc.interpreter.IMain) engine).settings().usejavacp().tryToSet(vals);
engine.eval("test.Singleton.instance");
Singleton.instance();
}
}
And here is the output:
java.lang.Thread.getStackTrace(Unknown Source)
test.Singleton.<init>(Singleton.java:10)
test.Singleton.<clinit>(Singleton.java:7)
$line3.$read$$iw$$iw$.<init>(<console>:8)
$line3.$read$$iw$$iw$.<clinit>(<console>)
$line3.$eval$.$result$lzycompute(<console>:5)
$line3.$eval$.$result(<console>:5)
$line3.$eval.$result(<console>)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:773)
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.callEither(IMain.scala:777)
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.evalEither(IMain.scala:792)
scala.tools.nsc.interpreter.IMain$WrappedRequest.eval(IMain.scala:613)
scala.tools.nsc.interpreter.IMain.eval(IMain.scala:1047)
javax.script.AbstractScriptEngine.eval(Unknown Source)
test.Main.main(Main.java:19)
java.lang.Thread.getStackTrace(Unknown Source)
test.Singleton.<init>(Singleton.java:10)
test.Singleton.<clinit>(Singleton.java:7)
test.Main.main(Main.java:20)
The stack trace shows that the script engine ends up creating a new instance of Singleton, but I got no idea why.
Thank you.

Found out the fix after browsing the source code:
((scala.tools.nsc.interpreter.IMain) engine).settings().embeddedDefaults(Main.class.getClassLoader());
This changes the ClassLoader for the ScriptEngine to the same one.

Related

Intercept method at runtime to return class instance

I'm trying to change some method code so it returns a fixed value, instead of actually executing the original code.
The idea is to create a loader that, using a json that specifies some class methods, specifies the result it should return (another json serializated instance). Something like that:
{
"overrides": [
{
"className": "a.b.C",
"method": "getUser",
"returns": "{ \"name\": \"John\" }"
}
}
}
The result should be that, each time C.getUser() is called, the serializated instance shoud be returned instead of actually executing the method (all this without changing the source code).
I've tried something like this:
ByteBuddyAgent.install();
final ClassReloadingStrategy classReloadingStrategy = ClassReloadingStrategy.fromInstalledAgent();
new ByteBuddy().redefine(className).method(ElementMatchers.named(methodName))
.intercept(FixedValue.nullValue()).make()
.load(clase.getClassLoader(), classReloadingStrategy);
And it returns null instead of executing the method body but, how can I return the deserializated result? When I try to une a FixedValue.value(deserializatedInstance) it throws the following exception:
> java.lang.RuntimeException: java.lang.IllegalStateException: Error invoking java.lang.instrument.Instrumentation#retransformClasses
at es.abanca.heracles.ServiceLauncher.addTiming2(ServiceLauncher.java:129)
at es.abanca.heracles.ServiceLauncher.establecerMocks(ServiceLauncher.java:65)
at es.abanca.heracles.ServiceLauncher.run(ServiceLauncher.java:40)
at es.abanca.heracles.MifidServiceLauncher.main(MifidServiceLauncher.java:6)
Caused by: java.lang.IllegalStateException: Error invoking java.lang.instrument.Instrumentation#retransformClasses
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:503)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$2.apply(ClassReloadingStrategy.java:568)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:225)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:100)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6156)
at es.abanca.heracles.ServiceLauncher.addTiming2(ServiceLauncher.java:127)
... 3 more
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:495)
... 8 more
Thank you all in advance
Your approach only works if the target class was not loaded yet.
When trying to modify (i.e. retransform) a class which was already loaded, as opposed to a class which is just being loaded (i.e. redefine), you need to make sure you
use retransform instead of redefine and
avoid manipulating the target class structure via .disableClassFormatChanges().
I am not a ByteBuddy expert, but I know you can modify methods without changing the class structure via Advice API. I usually do it like this:
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.ClassFileLocator;
import org.acme.Sub;
import java.lang.instrument.Instrumentation;
import static net.bytebuddy.agent.builder.AgentBuilder.RedefinitionStrategy.RETRANSFORMATION;
import static net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;
import static net.bytebuddy.matcher.ElementMatchers.is;
import static net.bytebuddy.matcher.ElementMatchers.named;
class Scratch {
public static void main(String[] args) {
System.out.println(new Sub("original name").getName());
Instrumentation instrumentation = ByteBuddyAgent.install();
new AgentBuilder.Default()
.with(RETRANSFORMATION)
.with(AgentBuilder.Listener.StreamWriting.toSystemError().withTransformationsOnly())
.disableClassFormatChanges()
.type(is(Sub.class))
.transform((builder, typeDescription, classLoader, module) ->
builder.visit(
Advice
.to(MyAspect.class, ClassFileLocator.ForClassLoader.ofSystemLoader())
.on(named("getName"))
)
)
.installOn(instrumentation);
System.out.println(new Sub("original name").getName());
}
static class MyAspect {
#Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class)
public static boolean before() {
// Default value for boolean is false -> skip original method execution
return false;
}
#Advice.OnMethodExit(onThrowable = Throwable.class, backupArguments = false)
public static void after(
#Advice.Return(readOnly = false, typing = DYNAMIC) Object returnValue
)
{
System.out.println("MyAspect");
// Here you can define your return value of choice, null or whatever else
returnValue = "dummy name";
}
}
}
The console log would be something like:
original name
[Byte Buddy] TRANSFORM org.acme.Sub [sun.misc.Launcher$AppClassLoader#18b4aac2, null, loaded=true]
MyAspect
dummy name
There might be a simpler way. If so, Rafael Winterhalter definitely knows better than I.
Your problem is that you are enhancing a class in way that makes it ineligible for retransformation since you are changing the class's signature. You can force Byte Buddy into attempting to preserve the original shape by adding:
new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE)
Doing so, Byte Buddy disables a few features but for a simple instrumentation such as FixedValue this has no effect.

Bukkit static reference to main class [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I'm making a bukkit plugin and am using a config.yml and have a boolean to access the config, but since i am referring to it in another class, it has to be static which i think is causing it to break. Not sure how to fix.
Error messages:
at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:673) [craftbukkit-1.8.8.jar:git-Bukkit-efe04b8]
net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:335) [craftbukkit-1.8.8.jar:git-Bukkit-efe04b8]
net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:629) [craftbukkit-1.8.8.jar:git-Bukkit-efe04b8]
net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:537) [craftbukkit-1.8.8.jar:git-Bukkit-efe04b8]
7:28:03 AM at java.lang.Thread.run(Thread.java:745) [?:1.8.0_65]
7:28:03 AM Caused by: java.lang.NullPointerException
7:28:03 AM at otherResources.PermissionHandler.getPerm(PermissionHandler.java:16) ~[?:?]
7:28:03 AM at main.Main.onCommand(Main.java:33) ~[?:?]
7:28:03 AM at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit-1.8.8.jar:git-Bukkit-efe04b8]
The code:
package main;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import otherResources.PermissionHandler;
public class Main extends JavaPlugin{
public void onEnable(){
new PermissionHandler(this);
getLogger().info("Green lantern class is now active.");
this.getConfig().addDefault("permsgl", "");
this.getConfig().options().copyDefaults(true);
saveConfig();
}
public void onDisable(){
getLogger().info("Green lantern class is not active.");
saveConfig();
}
#SuppressWarnings("deprecation")
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
Player p = (Player) sender;
if(cmd.getName().equalsIgnoreCase("pring") && otherResources.PermissionHandler.getPerm(p)){
ItemStack PowerRing = new ItemStack(Material.SLIME_BALL);
ItemMeta PowerRingMeta = PowerRing.getItemMeta();
PowerRingMeta.setDisplayName(ChatColor.GREEN + "Power Ring");
PowerRingMeta.setLore(Arrays.asList(ChatColor.DARK_GREEN + "Mode: Laser"));
p.getInventory().addItem(PowerRing);
Bukkit.broadcastMessage("Spawn Ring is in Order");
return true;
}
if(cmd.getName().equalsIgnoreCase("gladd") && (p.isOp())){
Player t = Bukkit.getServer().getPlayer(args[1]);
otherResources.PermissionHandler.givePerm(t);
Bukkit.broadcastMessage("Spawn Ring is in Order");
if(!t.isOnline()){
p.sendMessage(ChatColor.RED + "ERROR! " + ChatColor.YELLOW + args[1] + " is either offline or does not exist." );
return true;
}
}
else{
return true;
}
return true;
}
}
If you look at your error message:
7:28:03 AM Caused by: java.lang.NullPointerException
7:28:03 AM at otherResources.PermissionHandler.getPerm(PermissionHandler.java:16) ~[?:?]
7:28:03 AM at main.Main.onCommand(Main.java:33) ~[?:?]
7:28:03 AM at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit-1.8.8.jar:git-Bukkit-efe04b8]
In your code, you're calling something on an object which is null
It's occurring here:
otherResources.PermissionHandler.getPerm(p) // line 33
because you are calling getPerm statically, like you said, and:
You assign your main variable in the constructor by doing this (post was edited, so the second class was removed):
public PermissionHandler(Main plugin) {
configGetter = plugin; // Assigning inside constructor
}
but then when you create the object, you don't use the variable:
public void onEnable(){
new PermissionHandler(this); // You create it, but don't assign it to a value, or use the value
}
So you are creating an instance of an object, but you are not using it, and you are calling a static method, meaning it has no knowledge of the variable.
In terms of fixing your problem:
but since i am referring to it in another class, it has to be static which i think is causing it to break. Not sure how to fix.
The simplest solution is to use a Singleton Design Pattern. It allows you to create a single instance of an object (so it will let you assign that Main variable) whilst providing a global reference to that object (i.e. you can use it like a static variable). I'd recommend reading up on it.
Other solutions:
Initialise the Main variable using a static method
Refactoring your plugin structure to remove the static requirement

About Adding import package in Groovy by customizing compilation process

I am writing a java file in which i am parsing the given groovy file using GroovyClassLoader to find the class in it. To do this, i have to import some class (like org.junit.Test) and add package and add static import also. Since i am using old groovy version 1.6, i can not use compilation customizers as these classes not available in this version. So to import custom classes, i had to write custom groovy class loader by extending groovy class loader class like below,
...
public static class DefaultImportClassLoader extends GroovyClassLoader {
public DefaultImportClassLoader(ClassLoader cl){
super(cl);
}
public CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource codeSource) {
CompilationUnit cu = super.createCompilationUnit(config, codeSource);
cu.addPhaseOperation(new SourceUnitOperation() {
public void call(SourceUnit source) throws CompilationFailedException {
//source.getAST().addImport("Test",ClassHelper.make("org.junit.Test")); //working
source.getAST().addImportPackage("org.junit.");
}}, Phases.CONVERSION);
return cu;
}
}
here add import package is not working. Would any one give right suggestion way of using addImportPackage().
I've tested your code and works perfectly for me. (with groovy-all-1.6.9.jar) (edit: groovy-all-1.6.0.jar works fine too)
How do you use your class DefaultImportClassLoader?
I've done:
public static void main(String[] args) throws InstantiationException, IllegalAccessException{
GroovyClassLoader loader = new DefaultImportClassLoader(new GroovyClassLoader());
Class groovyClass = loader.parseClass(DefaultImportClassLoader.class.getClassLoader().getResourceAsStream("so_22729226/test.groovy"));
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
groovyObject.invokeMethod("run", null);
}
With this Groovy class:
class so_22729226_Test {
def run(){
print Test.class
}
}
And I get the expected output: interface org.junit.Test
If I use the standard loader I get:
Caused by: groovy.lang.MissingPropertyException: No such property: Test for class: so_22729226_Test
Which is the expected behaviour too.

Obtaining all the methods in a class --- error prone

I am new to reflection and to practice, I downloaded a random Java project from a website. I decided to find out which class has the main method so I wrote the following code:
package reflection;
import java.io.IOException;
import java.lang.reflect.*;
import java.nio.file.*;
public class FindMethods {
public static void main(String[] args) throws IOException{
if(args.length==0){
System.out.println("Exiting");
System.exit(1);
}else{
Path p = Paths.get(args[0]);
DirectoryStream<Path> allClassFiles = Files.newDirectoryStream(p, "*.class");
for(Path each : allClassFiles){
// System.out.println(each.getFileName());
try {
findMethods(each.getFileName().toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
public static void findMethods(String file) throws ClassNotFoundException{
System.out.println(file);
Class c = Class.forName(file);
Method[] m = c.getDeclaredMethods();
for(Method each : m){
System.out.println(each.toString());
}
}
}
System.out.println(each.getFileName()); properly returns the .class files in the folder however, it is interspersed with stack trace of ClassNotFoundException
The classes are as follows:
Addwindow$1.class
Addwindow$2.class
Addwindow.class
Authorwindow.class
clsConnection.class
clsSettings$1.class
clsSettings.class
Deletewindow$1.class
Deletewindow$2.class
Deletewindow.class
Editwindow$1.class
Editwindow$2.class
Editwindow.class
Emprptwindow$PrintCommand.class
Emprptwindow.class
Helpwindow.class
LoginFrame$1.class
LoginFrame.class
MainMenu$1.class
MainMenu$2.class
MainMenu.class
Payrptwindow.class
printwindow$1.class
printwindow.class
Settingswindow$1.class
Settingswindow.class
What changes do I need to make to the code to get the methods from each class ?
Stack trace:
java.lang.ClassNotFoundException: Settingswindow
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at reflection.FindMethods.findMethods(FindMethods.java:33)
at reflection.FindMethods.main(FindMethods.java:22)
Random project being talked about:
http://projectseminar.org/java-projects/payroll-accounting-system/98/
.class is part of the filename, but it isn't part of the class name. You need to strip it before passing it to Class.forName.
Another issue is that forName expects packages to be separated using periods, rather than than slashes or whatever directory separator your filesystem uses. If everything is in the default package, this shouldn't be an issue though.
If it's still not working, you should double check the classpath.
Class names that contain a $ are anonymous classes within the outer class (determined by the name to the left of the $). You can safely ignore those in your search for main. Just test for the presence of a $ in the class names in your main loop and skip the processing.
Without knowing more about what app you are looking at, I can't say why your code can't find some of the other classes (like clsConnection).
There is a problem in this approach - you load all project's classes. It is better to analize classes without loading them. There are tools for that. Here's what we can do with http://www.jboss.org/javassist
public static void findMethods(String file) throws Exception {
ClassPool cp = ClassPool.getDefault();
try (InputStream is = new FileInputStream(file)) {
CtClass cc = cp.makeClass(is);
for (CtMethod m : cc.getMethods()) {
System.out.println(m);
}
}
}

Why the Class cannot be seen in its source file Java

Whatever I do I cannot create new instance of class Serwer. Please help, somehow constructor is invisible. I don't understand why is it so. The constructor is public and everything is coded in one file.
I just get this:
java.rmi.StubNotFoundException: Stub class not found: Serwer_Stub; nested exception is:
java.lang.ClassNotFoundException: Serwer_Stub
at sun.rmi.server.Util.createStub(Unknown Source)
at sun.rmi.server.Util.createProxy(Unknown Source)
at sun.rmi.server.UnicastServerRef.exportObject(Unknown Source)
at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)
at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)
at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.exportObject(Unknown Source)
at javax.rmi.PortableRemoteObject.exportObject(Unknown Source)
at javax.rmi.PortableRemoteObject.<init>(Unknown Source)
at Serwer.<init>(Serwer.java:13)
at Serwer.main(Serwer.java:35)
Caused by: java.lang.ClassNotFoundException: Serwer_Stub
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
... 10 more
CLASS
import java.rmi.RemoteException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.rmi.PortableRemoteObject;
public class Serwer extends PortableRemoteObject implements MyInterface {
public Serwer() throws RemoteException {
super();
try{
Serwer ref =
new Serwer();
Context ctx = new InitialContext();
ctx.rebind("myinterfaceimplementacja", ref);
}catch(Exception e){e.printStackTrace();}
}
#Override
public String echo(String napis) throws RemoteException {
return "echo" + napis;
}
#Override
public int dodaj(int wrt1, int wrt2) throws RemoteException {
return wrt1 + wrt2;
}
public static void main(String[] args){
try {
new Serwer();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
There are two bugs in your code. The first one is the obvious infinite recursion in the Serwer constructor, where you are calling the constructor again and again. This can be fixed by removing that line from the constructor and replace ref with this on the following line:
public class Serwer extends PortableRemoteObject implements MyInterface {
public Serwer() throws RemoteException {
super();
}
#Override
public String echo(String napis) throws RemoteException {
return "echo" + napis;
}
#Override
public int dodaj(int wrt1, int wrt2) throws RemoteException {
return wrt1 + wrt2;
}
public static void main(String[] args){
try {
Serwer ref = new Serwer();
// Context ctx = new InitialContext();
// ctx.rebind("myinterfaceimplementacja", ref);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
However, this bug is unrelated to the ClassNotFoundException you got. What causes the exception is that you use PortableRemoteObject as the base class of your remote implementation. Normally in Java RMI, the stub class (Serwer_Stub) is generated automatically when you export (instantiate) the remote object. But the PortableRemoteObject is an exception to this case. You can solve this two ways:
As Kumar suggested, replace the javax.rmi.PortableRemoteObject with java.rmi.server.UnicastRemoteObject. This way the stub object gets created automatically, and the above code will run happily, I tested it.
public class Serwer extends UnicastRemoteObject implements MyInterface {
If for some reason you must use PortableRemoteObject, then you should generate the stub class manually by using the RMI compiler (rmic) tool that are shipped with the JDK.
First, you compile the Serwer class:
javac Serwer.java
This will generate the Serwer.class file. Then you call the RMIC tool to generate the stub class:
rmic Serwer
This will generate the Serwer_Stub.class file. Now you can run your server:
java Serwer
I also tested this, it starts without any exceptions.
Note that there is another bug in your code with the usage of the Java Naming, causing another exception (NoInitialContextException), but that is also unrelated with the question, that's why I commented it out in the code above. Since I'm no expert in javax.naming, it's up to someone else to help you with that.
Maybe you intended to use RMI registry instead of using Naming by mistake. RMI registry is the native way to bind and lookup remote objects in Java RMI. In this case you should replace the
Context ctx = new InitialContext();
ctx.rebind("myinterfaceimplementacja", ref);
lines with the appropriate RMI registry code:
Registry reg = LocateRegistry.createRegistry(1099);
reg.rebind("myinterfaceimplementacja", ref);
This will create the RMI registry for you on the standard port (1099). If you run your program, the registry will be created and your remote object will be exported and registered under the given name.
The other way is to write
Registry reg = LocateRegistry.getRegistry();
This makes your program to find an existing registry that is already running. You must start the RMI registry before running your program, by calling the remiregistry tool, that is also part of the JDK:
rmiregistry
Now you can compile and you start your program:
javac Serwer.java
java Serwer
It will start and register your remote object implementation in the registry, making it available to be looked up by the clients.

Categories