In JShell, how to load Java code from a string? - java

I have implemented a method that generates Java code:
public static String generate() { ... }
It returns Java code as a String, i.e. I might get
"public class X { public static String x() { return \"x\"; } }"
as a value returned by generate. Now, I am in a JShell Tool (JEP-222) session, and I can call generate, but I fail to load the result of generate into JShell itself.
Ideally I'd like to achieve the following
jshell> eval(generate());
| created class X
jshell> X.x();
$2 ==> "x"
In the above (hypothetical) JShell sesssion, eval is the function that I am looking for.
Possible solutions I already tried:
I know that this would be possible by calling JShell#eval but I failed to obtain the JShell object that represents the currently running JShell.
It might be that there is some facility in JShell that allows lifting a String to a Snippet. I couldn't find something like that, but if there is, it might be helpful.
I know that I can /open a file, so it might be possible to write the String to a file and then open/load it. However this is a two-step process, and I would prefer to have a solution that is simpler.

Related

Read the class file and replace content of the class file

I am compiling this Java file and I get one class file.
My task is to change the Static content "Hello" in the Class file and replace with "Hi".
How to read the Class file first, and how to replace the static content?
public class test {
public static void main(String[] args) {
System.out.println("Hello");
}
}
Is there any standard code(A template) for that ?
You need to use some Java bytecode instrumentation libraries like ASM. Good to start to read links are:
A Guide to Java Bytecode Manipulation with ASM
How To Modify Constant Pool Using ASM?
Does your solution need to be in Java? You can use Jawa to accomplish the same in Python with a lot less boilerplate than ASM and its equivalents.
Install it: pip install jawa
Then:
from jawa.constants import String
from jawa.classloader import ClassLoader
# Create a ClassLoader for the current directory
# and load your "test" class.
test = ClassLoader('.')['test']
# Find the first String with the value "Hello"
# in the constant pool.
constant = test.constants.find_one(
type_=String,
f=lambda c: c.string.value == 'Hello'
)
# Change it to your new value
constant.string.value = 'Hi'
# ... and save the new class.
with open('test.class', 'wb') as new_test:
test.save(new_test)
Result:
$ java test
Hi
Full documentation is at http://jawa.tkte.ch. Regardless of what tool you end up using it's absolutely required to read the JVM ClassFile specification or you won't really understand what's going on. You can find it at https://docs.oracle.com/javase/specs/jvms/se10/html/jvms-4.html.

Can we run a Java program without main method?

For example I want to print statement like -
System.out.println("Hello");
How can the above line be printed on console without using the public static void main(String arg[]); in the class.
You will soon be able to do that with JShell, this allow you to type java expression in a shell to get the result, without having to compile the program. Here is a simple example from JShell - Java 9 interpreter (REPL) - Getting Started and Examples
> jdk-9/bin/jshell -v
jshell> void helloJShell() { System.out.println("hello JShell"); }
| created method helloJShell()
jshell> helloJShell();
hello JShell
You could then simply do
jshell> System.out.println("hello");
I didn't get time to try this yet but it look as simple as this.

Java Constructors in a Ruby Script

I'm trying to figure out how to add constructor parameters to my JRuby Script. I have had it working before with the following code.
class Man < NpcCombat
def attackScripts attacker, victim
return [BasicAttack.meleeAttack(attacker, victim,AttackStyle::Mode::MELEE_ACCURATE, 2, Weapon::FISTS)]
end
end
However the Java Class "NpcCombat" now has a integer parameter, such as NpcCombat(int). I'm trying to figure out how to change this in my ruby script, but it's not working.
I've never used jruby, but based on Ruby I imagine adding an initialize block that calls the super constructor should work:
class Man < NpcCombat
def initialize(num)
super(num)
end
...
end

Problems in passing contents of xml file as string to native function

I want to pass String containing contents of xml file to native function using JNA .But somehow it is giving me problems. The program goes into infinite loop and does not get terminated. The same thing is working when I am trying to access DLL through C.
This is how my code looks like -
Native side --
Class ABC{
...
long t = processValues(const * str1 ,char** output);
...}
JNA interface looks llke this -
public interface Add extends Library
{
Add INSTANCE = (Add) Native.loadLibrary("add", Add.class);
...
NativeLong processValues(String str1,PointerByReference output);
...}
main method in java class is as follows -
public static void main(String args[]){
Add lib = Add.INSTANCE;
PointerByReference ptrRef = new PointerByReference();
String strBuffer = "<?xml version= \"1.0\" ?><NRECORD> <SUBRECORD><ITEM1> <NAME> pqr</NAME> <MDATE>10/12/2012</MDATE><ENGINEER>TMAY</ENGINEER></ITEM1></SUBRECORD></NRECORD> "
Nativelong p = lib.processValues(strBuffer,ptrRef);
}
The program goes into infinite loop and never get terminated. DLL uses recursive function to parse input xml string, I think this is where problem lies. (I am using third party dll so cant access code.) But function processValues() get executed successfully when same dll is accessed through C.(with same input parameters) My questions are
is this right way to pass xml contents as string?
Is there any way by which I can get event logs how the dll functions are getting called.
Thanks in advance.

How to embed version strings in java classes

We'd like to have the version of the java source code, in our case the svn $Id$ string, embedded in the generated class file.
We'd like to be able to determine this information from a static inspection of the class file, preferably by running the strings or what command.
A naive attempt to declare a private final static String variable set to this value inside each class didn't result in a legible string embedded in the class file.
You said ... preferably by running the strings or what command ...
Let's assume you have something like this in your code:
private static final String SVN_ID =
"$Id: SvnIdDemo.java 1081 2008-09-30 19:03:23Z john $";
The following Perl one-liner ...
$ perl -nwe 'print "$1\n" if /.*(\$Id:[^\$]+\$).*/' SvnIdDemo.class
... prints the SVN ID string to STDOUT.
$Id: SvnIdDemo.java 1081 2008-09-30 19:03:23Z john $
You could add a method to the bottom of each class with a predefined name. Say you used:
public String extractChaimGeretzVersionNumber() {
return "$Id$";
}
Then you find the version with a program that loads the class and, via reflection, calls the magic method and retrieves the version.
You would either have to have code that inserted the method to the .java files before building the .class and .jar files OR you could have a build step that checked that the magic method was already in every one of them. Fail the build if not found.

Categories

Resources