I am using RxBinding for Android widgets. I would like to do the following: Observable<java.lang.Void> obs = RxView.clicks(button);
But I get a compile time error saying that the expected type is kotlin.Unit. RxView.clicks(button) returns an Observable<Unit>but I don't think that Java has a Unit datatype.
How do I get an Observable<Void> in Java?
You can live with Observable<Unit> in Java. kotlin.Unit is a class file available for java programs as soon as kotlin-stdlib-<some version>.jar is in your class path, and it is there already because it is required by RxBinding.
If, however, some other part of your program requires Observable<Void>, it can be obtained with:
Observable<Unit> ou = RxView.clicks(button);
Observable<Void> ov = ou.as(unit->null);
Related
I'm trying to redefine a method at runtime using javassist, but I'm running into some issues on the last step, because of the weird requirements I have for this:
I can't require the user to add startup flags
My code will necessarily run after the class has already been defined/loaded
My code looks like this:
val cp = ClassPool.getDefault()
val clazz = cp.get("net.minecraft.world.item.ItemStack")
val method = clazz.getDeclaredMethod(
"a",
arrayOf(cp.get("net.minecraft.world.level.block.state.IBlockData"))
)
method.setBody(
"""
{
double destroySpeed = this.c().a(this, $1);
if (this.s()) {
return destroySpeed * this.t().k("DestroySpeedMultiplier");
} else {
return destroySpeed;
}
}
""".trimIndent()
)
clazz.toClass(Items::class.java)
(I'm dealing with obfuscated method references, hence the weird names)
However, calling .toClass() causes an error as there are then two duplicate classes on the class loader - and to my knowledge there's no way to unload a single class.
My next port of call to update the class was to use the attach API and an agent, but that requires a startup flag to be added (on Java 9+, I'm running J17), which I can't do given my requirements. I have the same problem trying to load an agent on startup.
I have tried patching the server's jar file itself by using .toBytecode(), but I didn't manage to write the new class file to the jar - this method sounds promising, so it's absolutely on the table to restart the server after patching the jar.
Is there any way I can get this to work with my requirements? Or is there any alternative I can use to change a method's behavior?
Has anyone attempted to "link" in the Rascal command line jar in a java executable and call REPL commands from this java executable?
I found a similar question on stackoverflow (Running a Rascal program from outside the REPL), but that doesn't go into details unfortunately.
I also checked the Rascal tutor site, but couldn't find any examples on how to do this. Tijs told me that it's something along the lines of "instantiate an interpreter and then call the import() function, after which the call() function can be called to inject REPL commands).
Is there any example code on how to do, e.g. the following from the tutor site on the REPL but from a java programming context instead of on the command line:
rascal>import demo::lang::Exp::Concrete::NoLayout::Syntax;
ok
rascal>import ParseTree;
ok
rascal>parse(#Exp, "2+3");
sort("Exp"): `2+3`
The following would do the trick; a utility class for the same can be found in rascal/src/org/rascalmpl/interpreter/JavaToRascal.java:
GlobalEnvironment heap = new GlobalEnvironment();
IValueFactory vf = ValueFactoryFactory.getValueFactory();
TypeFactory TF = TypeFactory.getInstance();
IRascalMonitor mon = new NullRascalMonitor();
Evaluator eval = new Evaluator(vf, new PrintWriter(System.err), new PrintWriter(System.out), new ModuleEnvironment(ModuleEnvironment.SHELL_MODULE, heap), heap);
eval.doImport(mon, "demo::lang::Exp::Concrete::NoLayout::Syntax");
eval.doImport(mon, "ParseTree");
eval.eval(mon, "parse(#Exp, \"2+3\");", URIUtil.rootLocation("unknown"));
There is also more efficient ways of interacting with the evaluator, via the pdb.values IValue interfaces to build data and ICalleableValue to call Rascal functions. You can use the above heap object to query its environments to get references to functions and you can use the low level pdb.values API to construct values to pass to these functions.
Caveat emptor: this code is "internal" API with no guarantee for backward compatibility. I can guarantee that something like this will always be possible.
I am working in android. For reading the file content, I am using the method
List<String> lines = Files.readAllLines(wiki_path);
But whem I am using this method I am getting this error:
The method readAllLines(Path) is undefined for the type MediaStore.Files.
Why can the compiler not find the method?
Path wiki_path = Paths.get("C:/tutorial/wiki", "wiki.txt");
try {
List<String> lines = Files.readAllLines(wiki_path);
for (String line : lines) {
if(url.contains(line))
{
other.put(TAG_Title, name);
other.put(TAG_URL, url);
otherList.add(other);
break;
}
}
}
The method you're trying to use is a member of java.nio.file.Files - but that class (and indeed that package) doesn't exist on Android. Even if the Java 7 version existed, you're trying to use a method introduced in Java 8. The Files class you've imported is android.provider.MediaStore.Files which is an entirely different class.
Even if it compiled, the path you're providing looks ever so much like a Windows path, which wouldn't work on an Android device...
I'm scratching my head on this one, The program is as follows:
class MyClass {
def static someMethod() {
def pb = new ProcessBuilder("")
pb.inheritIO()
pb.setCommand(/* command list */)
def process = pb.start()
...
println "profit"
}
}
except running the above (or the equivelant of) gives the output:
No signature of method: java.lang.ProcessBuilder.inheritIO() is applicable for argument types: () values: []
inheritIO is obviously a method defined in the ProcessBuilder class
so what is going wrong here?
CONTEXT: this is happening during a gradle build using jdk 7u55 except i imagine this info is unrelated. to me it looks like groovy has forgotten what it was doing.
EDIT: if i delete the pb.inheritIO() line then when i call pb.start() it throws another error:
java.lang.ArrayStoreException
Turns out the answer is quite involved but very specific to my setup:
although i have my org.gradle.java.home property set to the java 1.7 jdk, I am using a properties plugin that uses different property files according to an environment variable called environmentName this property was set to the incorrect value thus it was reading JAVA_HOME from my environment rather than the variable i set in the property file i wanted. I changed this and the jre was switched to the correct runtime.
I have a Ruby script that I'd like to run at the startup of my Java program.
When you tell the ScriptEngine to evaluate the code for the first time, it takes a while. I'm under the impression that the reason it takes this long is because it first needs to compile the code, right?
I found that you can compile Ruby code, and then evaluate it later. The evaluation itself is fast - the compilation part is the slow one. Here I am compiling:
jruby = new ScriptEngineManager().getEngineByName("jruby");
Compilable compilingEngine = (Compilable)jruby;
String code = "print 'HELLO!'";
CompiledScript script;
script = compilingEngine.compile(code);
This snippet is what takes a while. Later when you evaluate it, it is fine.
So of course, I was wondering if it would be possible to "save" this compiled code into a file, so in the future I can "load" it and just execute it without compiling again.
As others have said, this is not possible with CompiledScript. However, with JRuby you have another option. You can use the command line tool jrubyc to compile a Ruby script to Java bytecode like so:
jrubyc <scriptname.rb>
This will produce a class file named scriptname.class. You can run this class from the command line as if it were a normal class with a main(String[] argv) method (note: the jruby runtime needs to be in the classpath) and you can of course load it into your application at runtime.
You can find more details on the output of jrubyc here: https://github.com/jruby/jruby/wiki/JRubyCompiler#methods-in-output-class-file
According to this, no.
"Unfortunately, compiled scripts are not, by default, serializable, so they can't be pre-compiled as part of a deployment process, so compilation should be applied at runtime when you know it makes sense."
I think some really easy cache will solve your problem:
class CompiledScriptCache {
static {
CompiledScriptCache INSTANCE = new CompiledScritCache();
}
publich static CompiledScriptCache get(){
retrun INSTANCE;
};
List<CompiledScript> scripts = new ArrayList<>();
public CompiledScript get(int id){
return scripts.get(id);
}
public int add(String code){
ScriptEngine jruby = new ScriptEngineManager().getEngineByName("jruby");
Compilable compilingEngine = (Compilable)jruby;
CompiledScript script;
script = compilingEngine.compile(code);
scripts.add(script);
return scripts.size()-1;
}
}
update
I thought this question was about avoiding to comile the source more than once.
Only other approach I could imagine is to create Java-Classes and make a cross-compile:
https://github.com/jruby/jruby/wiki/GeneratingJavaClasses