I'm trying to debug an java eclipse project with some problem!
I'm starting using CGLIB to make faster reflection calls using the index metod.
example
FastClass fastClass = FastClass.create(getClass());
int index = fastClass.getIndex("methodName", new Class[] { Object.class });
fastClass.invoke(index, this, new Object[] { obj } );
now when i try to put a breakpoint into a class that is called by fastreflection method this is the eclipse output.
I try to change compiler option on generate line number with no results.
I also upload an eclipse project (built with Juno version) that replicates the problem!!
http://www.filefactory.com/file/4zryz3gjgbyh/n/FastDebug.rar
Thanks!
I "resolved"(understand) the problem, but it is not a problem with Eclipse. When you launch
the program this line: FastClass.create(ReflectionTarget.class); ends up
creating an entirely new version of the compiled class removing all
non-essential stuff from the classfile to make it "fast" - that includes all
the line number / debug infos, which means the breakpoint cannot be set in it.
http://cglib.sourceforge.net/xref/net/sf/cglib/core/package-summary.html
There's no javadoc and you need to read the source but now i understand this is not a
problem but a feature of this method to make fast reflection!
Related
I am having the following problem:
I have an Enum that was originally declared with 5 elements.
public enum GraphFormat {
DOT,
GML,
PUML,
JSON,
NEO4J,
TEXT {
#Override
public String getFileExtension() {
return ".txt";
}
};
Now I need to add an additional element to it (NEO4J). When I run my code or try to debug it I am getting an exception because the value can't be found in the enum.
I am using IntelliJ as my IDE, and have cleaned the cache, force a rebuild, etc.. and nothing happens. When I look at the .class file created on my target folder, it also has the new element.
Any ideas on what could be causing this issue ?
I found my problem and want to share here what was causing it. My code was actually for a Maven plug-in which I was pointing to another project of mine to run it as a goal. However the pom.xml of my target test project was pointing to the original version of the plug-in instead of the one I am working on, and that version of course is outdated and does not include the new value. Thank you.
My project requires Java 1.6 for compilation and running. Now I have a requirement to make it working with Java 1.5 (from the marketing side). I want to replace method body (return type and arguments remain the same) to make it compiling with Java 1.5 without errors.
Details: I have an utility class called OS which encapsulates all OS-specific things. It has a method
public static void openFile(java.io.File file) throws java.io.IOException {
// open the file using java.awt.Desktop
...
}
to open files like with double-click (start Windows command or open Mac OS X command equivalent). Since it cannot be compiled with Java 1.5, I want to exclude it during compilation and replace by another method which calls run32dll for Windows or open for Mac OS X using Runtime.exec.
Question: How can I do that? Can annotations help here?
Note: I use ant, and I can make two java files OS4J5.java and OS4J6.java which will contain the OS class with the desired code for Java 1.5 and 1.6 and copy one of them to OS.java before compiling (or an ugly way - replace the content of OS.java conditionally depending on java version) but I don't want to do that, if there is another way.
Elaborating more: in C I could use ifdef, ifndef, in Python there is no compilation and I could check a feature using hasattr or something else, in Common Lisp I could use #+feature. Is there something similar for Java?
Found this post but it doesn't seem to be helpful.
Any help is greatly appreciated. kh.
Nope there isn't any support for conditional compilation in Java.
The usual plan is to hide the OS specific bits of your app behind an Interface and then detect the OS type at runtime and load the implementation using Class.forName(String).
In your case there no reason why you can't compile the both OS* (and infact your whole app) using Java 1.6 with -source 1.5 -target 1.5 then in a the factory method for getting hold of OS classes (which would now be an interface) detect that java.awt.Desktop
class is available and load the correct version.
Something like:
public interface OS {
void openFile(java.io.File file) throws java.io.IOException;
}
public class OSFactory {
public static OS create(){
try{
Class.forName("java.awt.Desktop");
return new OSJ6();
}catch(Exception e){
//fall back
return new OSJ5();
}
}
}
Hiding two implementation classes behind an interface like Gareth proposed is probably the best way to go.
That said, you can introduce a kind of conditional compilation using the replace task in ant build scripts. The trick is to use comments in your code which are opened/closed by a textual replacement just before compiling the source, like:
/*{{ Block visible when compiling for Java 6: IFDEF6
public static void openFile(java.io.File file) throws java.io.IOException {
// open the file using java.awt.Desktop
...
/*}} end of Java 6 code. */
/*{{ Block visible when compiling for Java 5: IFDEF5
// open the file using alternative methods
...
/*}} end of Java 5 code. */
now in ant, when you compile for Java 6, replace "IFDEF6" with "*/", giving:
/*{{ Block visible when compiling for Java 6: */
public static void openFile(java.io.File file) throws java.io.IOException {
// open the file using java.awt.Desktop
...
/*}} end of Java 6 code. */
/*{{ Block visible when compiling for Java 5, IFDEF5
public static void openFile(java.io.File file) throws java.io.IOException {
// open the file using alternative methods
...
/*}} end of Java 5 code. */
and when compiling for Java 5, replace "IFDEF5". Note that you need to be careful to use // comments inside the /*{{, /*}} blocks.
You can make the calls using reflection and compile the code with Java 5.
e.g.
Class clazz = Class.forName("java.package.ClassNotFoundInJavav5");
Method method = clazz.getMethod("methodNotFoundInJava5", Class1.class);
method.invoke(args1);
You can catch any exceptions and fall back to something which works on Java 5.
The Ant script introduced below gives nice and clean trick.
link: https://weblogs.java.net/blog/schaefa/archive/2005/01/how_to_do_condi.html
in example,
//[ifdef]
public byte[] getBytes(String parameterName)
throws SQLException {
...
}
//[enddef]
with Ant script
<filterset begintoken="//[" endtoken="]">
<filter token="ifdef" value="${ifdef.token}"/>
<filter token="enddef" value="${enddef.token}"/>
</filterset>
please go to link above for more detail.
In java 9 it's possible to create multi-release jar files. Essentially it means that you make multiple versions of the same java file.
When you compile them, you compile each version of the java file with the required jdk version. Next you need to pack them in a structure that looks like this:
+ com
+ mypackage
+ Main.class
+ Utils.class
+ META-INF
+ versions
+ 9
+ com
+ mypackage
+ Utils.class
In the example above, the main part of the code is compiled in java 8, but for java 9 there is an additional (but different) version of the Utils class.
When you run this code on the java 8 JVM it won't even check for classes in the META-INF folder. But in java 9 it will, and will find and use the more recent version of the class.
I'm not such a great Java expert, but it seems that conditional compilation in Java is supported and easy to do. Please read:
http://www.javapractices.com/topic/TopicAction.do?Id=64
Quoting the gist:
The conditional compilation practice is used to optionally remove chunks of code from the compiled version of a class. It uses the fact that compilers will ignore any unreachable branches of code.
To implement conditional compilation,
define a static final boolean value as a non-private member of some class
place code which is to be conditionally compiled in an if block which evaluates the boolean
set the value of the boolean to false to cause the compiler to ignore the if block; otherwise, keep its value as true
Of course this lets us to "compile out" chunks of code inside any method. To remove class members, methods or even entire classes (maybe leaving only a stub) you would still need a pre-processor.
if you don't want conditionally enabled code blocks in your application then a preprocessor is only way, you could take a look at java-comment-preprocessor which can be used for both maven and ant projects
p.s.
also I have made some example how to use preprocessing with Maven to build JEP-238 multi-version JAR without duplication of sources
Java Primitive Specializations Generator supports conditional compilation:
/* if Windows compilingFor */
start();
/* elif Mac compilingFor */
open();
/* endif */
This tool has Maven and Gradle plugins.
hi I have got similar problem when I have shared library between Java SDK abd Android and in both environments are used the graphics so basically my code must to work with both
java.awt.Graphics and android.graphics.Canvas,
but I don't want to duplicate almost any code.
My solution is to use wrapper, so I access to graphisc API indirectl way, and
I can change a couple of imports, to import the wrapper I want to compile the projects.
The projects have some cone shaded and some are separate, but there is no duplicating anything except of couple of wrappers etc.
I think it is the best what I can do.
I have the following program which adds a method to itself when run. But I have to refresh it every time using the F5 button or the refresh option.
Is there a way I could code the refresh in the program itself so that it refreshes itself after the modification? The project I am working on is a Java application and not an eclipse plugin so as far as I know the refreshLocal() method can't be used.
public class Demo {
public static void main(String[] args) throws IOException, CoreException {
File file = new File("/home/kishan/workspace/Roast/src/Demo.java");
if (file.exists()) {
JavaClassSource javaClass = Roaster.parse(JavaClassSource.class,
file);
javaClass.addMethod().setPublic().setStatic(true)
.setName("newMethod").setReturnTypeVoid()
.setBody("System.out.println(\"newMethod created\");")
.addParameter("String[]", "stringArray");
FileWriter writer = new FileWriter(file);
writer.write(javaClass.toString());
writer.flush();
writer.close();
}
}
}
I have tried using the refreshLocal() method defined in the eclipse JDT but since my project is a Java application the ResourcePlugin.getWorkspace() method does not work giving me a "workspace closed" error. Any suggestion is appreciated.
You see, eclipse runs your Java class within its own dedicated JVM. Thus there is no direct programmatic way of enforcing a refresh within eclipse.
You could check this older question; maybe that could lead to a reasonable workarounds.
On the other hand you might step back and ask yourself why exactly you want to achieve that. Your workflow simply doesn't make much sense when looking at it; as in: when generating code that way, shouldn't that generated code better go in its own specific place?
If you intend to "generate" code frequently to then continue to use it in eclipse; well, that somehow smells like a strange idea.
Eclipse has "Refresh using native hooks or polling" which might might help.
You can find it under Window > Prefrences > General > Workspace.
See On Eclipse, what does "Preferences -> General -> Workspace -> Refresh using native hooks or polling" do?
I have a problem integrating Java code into KNIME. Similar posts on Knime forum (http://tech.knime.org/forum/knime-general/using-external-jar-in-java-snippet-node-workflow-not-able-to-initialize-class-of) were of little help and I also posted a question there but have not got answer so far, so I'm trying my luck here.
I am trying to integrate my code into KNIME workflow using JavaSnippet. I have exported the code into a jar and put it into the KNIME jre/lib/endorsed folder. The code references CDK 1.4.19 and I have also placed the corresponding jar file into the same directory. I do not have CDK node extensions installed in KNIME and using them is also not an option in my case.
The code starts with:
IChemObjectBuilder builder = SilentChemObjectBuilder.getInstance();
SmilesParser sp= new SmilesParser(builder);
When I try to execute JavaSnippet I get the following exception message:
Evaluation of java snippet failed for row "Row0". Exception message: Could not initialize class org.openscience.cdk.smiles.SmilesParser
When I just try
IChemObjectBuilder builder = SilentChemObjectBuilder.getInstance();
It works and I get no exception message. I have checked, the builder is not a null. However, when I try to initialize SmilesParser, it fails. This class is public. It has no default constructor and has one public constructor that takes IChemObjectBuilder as a parameter.
I have tried to use class loader:
URL[] classLoaderUrls = new URL[]{new URL("file:///path on my computer/knime_2.9.4/jre/lib/endorsed/cdk-1.4.19.jar")};
URLClassLoader urlClassLoader = new URLClassLoader(classLoaderUrls);
Class<?> parserClass = urlClassLoader.loadClass("org.openscience.cdk.smiles.SmilesParser");
Class[] classParameters = new Class[] {IChemObjectBuilder.class};
Constructor<?> constructor = parserClass.getConstructor(classParameters); //until this line there are no problems
Object parser = constructor.newInstance(builder); //fails here with the same exception message: Could not initialize class org.openscience.cdk.smiles.SmilesParser
I am sure that this is not a CDK error because I can execute the code in Eclipse.
Why can a constructor of one class be called from KNIME without any problems and a constructor of another class can not??
I would be very grateful if you could suggest a solution or a probable reason why this happens.
Thank you!
Ok, finally solved the problem myself. Cleaned project meta data, cleaned endorsed library directory, switched KNIME workspace to another directory, put all jars into one folder and added them as external libraries. Now it works:)
I created my own new R library (called "Media"). There is no problem when I try to load it with RGui, and I can call the functions defined in the new package. This is how I load it:
> library(Media)
But, I'm also trying to call that functions from Java/JRI code, and when I load the new R package, Java doesn't seem to find the pacakge, throwing the message "Error in library(Media) : object 'Media' not found"
This is my current code using JRI:
REXP rexpSetFolder = re.eval("setwd('C:/Users/Albert/Documents')");
REXP rexpFolder = re.eval("getwd()");
System.out.println(rexpFolder.asString());
REXP rexpLoad = re.eval("library(Media)"); // fails
It also fails without the 'setwd' command, and simple calls to existing R functions work fine. I'm using R 2.10 and the latest JRI 0.5-0 under Windows.
Any help would be appreciated.
Thank you very much.
Edit:
The parameter lib.loc seems to work, at least this sentence does not return an error:
library("Media", lib.loc = "c:/Users/Albert/Documents")
But after that, calling a function in the package with re.eval("myfunction()"); still fails, as the function is not properly found.
You can modify the library path - see ?.libPaths in R, you simply want to add your private library to the path. The GUI does that for you, but if you are outside it doesn't happen. For example:
re.eval(".libPaths('c:/users/foo/Documents/R')");
Then load your package.
Did you install the library properly first? You might want to try using the lib.loc parameter.
library("Media", lib.loc = "c:/Users/Albert/Documents")
My work-around was to copy the package from my personal library (%USERPROFILE%\Documents\R) to the global library (%R_HOME%\library).
It's not the best because this requires Administrator privileges which not all users will have...