I am creating a program along the lines of Codingbat.com.
During Runtime, it needs to compile code, and then execute it. This has all been handled.
Currently, I am forced to use the JavacTool, which requires it to be packed alongside.
I have 2 basic questions:
1) How can I stop the ToolProvider.getSystemJavaCompiler() from returning null when ran from an executable jar?
2) If the above is not possible, is there a way to add the jar of com.sun.tools.javac.api.JavacTool; without having it as a referenced library, so that it acts like a regular import?
Thanks for answering this, if you would like, I could upload the Jar with the referenced library, and the jar without it.
Just to be clear, the one with the referenced library works, but it is way to large, and slower then the jar that is ran through eclipse, that uses the JavaCompiler, not the JavacTool
Thanks
Edit:
I am pretty sure this is possible with java as I have seen it before, yet forget where and how.
I suspect it's just a problem of which version of Java you run. If you run the version which comes with the JRE, it won't have the tools available. If you run the version which comes with the JDK, it will.
As an example, here's a short but complete program:
import javax.tools.*;
public class Test
{
public static void main(String[] args)
{
System.out.println(ToolProvider.getSystemJavaCompiler());
}
}
Running it with the JRE version of java.exe on my laptop:
c:\Users\Jon\Test>"\Program Files\java\jre7"\bin\java Test
null
And now with the JDK:
c:\Users\Jon\Test>"\Program Files\Java\jdk1.7.0"\bin\java Test
com.sun.tools.javac.api.JavacTool#441944ae
So try explicitly specifying the a Java binary associated with the JDK.
So you already know that all your users will have a JDK installed and you know how to find the classpath of the JDK when you're in your Java program. You don't need to load a DLL. You need to load the com.sun.tools.javac.api.JavacTool class in tools.jar. See How to load a jar file at runtime on how to load tools.jar
Related
I'm a n00b coder. I found an interesting library and trying to start toying with it. Which is not going great. This library is from 99' and uses JUnit (which I'm unfamiliar with) so there is a lot of confusing stuff. But it seems like the source of my failing even more elementary. Namely I have troubles importing packages.
This library has a test called StandardEvalTest.java. I moved to it to main Java directory and now I'm trying and failing to launch it using JUnit.
This package path org.pokersource.game.Deck goes directly from the directory where the test StandardEvalTest.java sits.
I also added the main java directory to the PATH environmental variable. Which as I assumed will allow import to locate the package.
None of those two things help. Also I was suspecting that maybe Deck.java and Deck.class are not enough and I have to do some work to create a package from it. But as far as I can say from Oracle doc the only thing needed is a package name in the header. Which seems to be present.
So I'm out of moves. Please help!
PS: Some additional info inspired by #Dhrubo 's answer:
The test I'm trying to run indeed sits in the main java folder of the library. (I moved it here hoping that when running from here it would be easier to find the package)
If I'm trying to compile the test instead of running it with JUnit he seem to fail to find JUnit classes and other JUnit related stuff.
[Oh OK I'm an idiot! Dont't mind me]
You should include the package while running StandardEvalTest.java as below
javac -cp [classpath] org.pokersource.game.StandardEvalTest.java
and run it from package root directory, I am assuming it is custom java file that you want to compile. You run directory should be parent of your package directory.
** I also see, you are trying to compile StandardEvalTest.java instead of Deck.java ... then check your StandardEvalTest.java file whether it exists in desired location.
I have received the task, at work, to find a way to use some methods from an existent jar file in a Python project. I have very limited experience in Python, but I have worked with that specific jar file before (it is part of a project we are working on). I am not allowed to modify much of both projects, and they are required to be as independent as possible.
I have researched multiple ways to include the jar methods in Python. So far, I have tried Jython (which I cannot use because the Python project uses PyQt among other libraries, which force the use of CPython, if my understanding is correct), Pyjnius and JPype. JPype seems the most promising, but I cannot get it working either. I have pasted the my code below, slightly censored because I don't know how much I am allowed to share.
from jpype import *
import jpype.imports
try:
jpype.addClassPath("jars/sdk.jar") #the relative path to the jar file
jpype.startJVM(convertStrings=False)
java.lang.System.out.println(jpype.getClassPath()) #printing the classpath to check, the path is correctly pointing to the sdk.jar file
java.lang.System.out.println("Hello world") #just to check if jpype is installed correctly, works
jpype.imports.registerDomain("a")
from a.b.c.d.e.f.g.h import SomeClass #fails here
except OSError as err:
print(err) # ToDo: Remove print when done
pass
The error I am getting is that the module a.b.c.d.e.f.g.h.SomeClass could not be found. I have tried different ways to give the path (absolute path, relative path, place the jar in different places in the project and outside of it), but that doesn't seem to be the problem, as the path printed is the correct absolute path to the jar file.
Also, the jar is used in other (Java) projects and it works. It is created using maven package (using IntelliJ, if it is relevant, and the same Java version as the one used by the JPype JVM). In the Java projects, the import would be:
import a.b.c.d.e.f.g.h.SomeClass;
I have copied this and just transformed the syntax into Python.
I have also tried to create the class with JObject (which I probably didn't do right anyway) and also tried the older syntax (to my understanding) with JPackage. For the JPackage way, I am getting the exception that the package a.b.c.d.e.f.g.h.SomeClass.someMethod is not Callable, which to my understanding is an equivalent exception to the one I'm getting using jpype imports. I have already gone through all the questions I could find here with similar problems, but none of those solutions have helped me.
Can anyone suggest some possible solution? Or can anyone see what I'm doing wrong? Suggestions of other possibilities to replace JPype are also welcomed. If there is any clarification needed, I will edit the question.
The only thing that seems likely if the jar is on the classpath and failed to import would be for there to be some missing dependency. You have two other ways to try loading the class which may provide additional diagnostics.
jpype.JClass("a.b.c.d.e.f.g.h.SomeClass")
and
jpype.JClass("java.lang.Class").forName("a.b.c.d.e.f.g.h.SomeClass")
The first is manually loading a class by full class specification. It is mechanically what is happening under the import. The second is calling for Java to load the class (bypassing all of JPype). It returns a java.lang.Class which can be passed to JClass to make a wrapper.
Common failures include missing a jar or native library, attempting to start JPype from within a module and having the wrong relative path, error in initialization of the class due to missing resource. JPype is just calling JNI calls, so if everything is fine on Java end it should work. Given that you checked the java.class.path System variable, it has to be something to do with class resources.
The JPype user manual has an alternatives section if you would like to try to find another package. Most of the alternatives with the exception of PyJnius appear to be unmaintained.
I am using Hot Code Replace feature when Tomcat is running from eclipse and it works great.
But, how can I do this manually when Tomcat is running outside eclipse?
After some searching, I have found that I need to use an agent like HotswapAgent. But, they are using this agent with modified JDK called DCEVM. I don't want to use modified JDK. I want to achieve the same thing with OpenJDK.
I know that modification will be limited to method body only but, that's not a problem for me. How can I achieve the exact same thing eclipse is doing for Hot Code Replace for an externally running Tomcat without using IDE?
Edit : Eclipse example is just to clarify what I want to achieve. I do not want to use eclipse at all. I just want to do Hot Code Replace in an application running in Tomcat.
Yes, it's possible to perform Hot Code Replace in a running JVM. This involves several steps.
Prepare (compile) the new version of classes you want to replace. Let's say, you want to replace org.pkg.MyClass, and the new version of this class is located at /new/path/org/pkg/MyClass.class
Create a Java Agent that uses Instrumentation API to redefine the given class. Here is how the simplest agent may look like:
import java.lang.instrument.*;
import java.nio.file.*;
public class HotCodeReplace {
public static void agentmain(String args, Instrumentation instr) throws Exception {
Class oldClass = Class.forName("org.pkg.MyClass");
Path newFile = Paths.get("/new/path/org/pkg/MyClass.class");
byte[] newData = Files.readAllBytes(newFile);
instr.redefineClasses(new ClassDefinition(oldClass, newData));
}
}
Compile the above agent and pack it into .jar with the following MANIFEST.MF
Agent-Class: HotCodeReplace
Can-Redefine-Classes: true
The command to create HotCodeReplace.jar:
jar cvfm HotCodeReplace.jar MANIFEST.MF HotCodeReplace.class
Load the agent .jar into the target JVM. This can be done with Attach API or simply with jattach utility:
jattach <pid> load instrument false /path/to/HotCodeReplace.jar
More about Java agents ยป
Does anyone have any idea why something that used to work before all of a sudden started giving this error? please help
java.lang.NoSuchMethodError: org.apache.hadoop.mapred.Counters.findCounter(Ljava/lang/Enum;)Lorg/apache/hadoop/mapreduce/Counter;
at edu.umn.cs.spatialHadoop.operations.Sampler.sampleMapReduceWithRatio(Sampler.java:214)
at edu.umn.cs.spatialHadoop.operations.Sampler.sample(Sampler.java:543)
at edu.umn.cs.spatialHadoop.operations.Repartition.packInRectangles(Repartition.java:494)
at edu.umn.cs.spatialHadoop.operations.Repartition.packInRectangles(Repartition.java:463)
at edu.umn.cs.spatialHadoop.operations.Repartition.repartitionLocal(Repartition.java:590)
This has been working earlier but suddenly started giving this error. I am using hadoop version 1.2.1
Counter class is included in hadoop-mapreduce-client-core.jar. You must have downgraded it somehow.
If you are using a build tool (maven, gradle...), check your dependencies and make sure they haven't changed. In case of doubt, just apply the latest version.
Else, go to your hadoop-mapreduce-client-core.jar and either check if the method is inside or just get a newer version to replace it in your project.
from org/apache/hadoop/mapreduce/Counter I guess that the hadoop-mapreduce-client-core.jar is missing
This is because of latest compiled class and dependent jar available in the application are of different version. For example: Let Class A compiled with dependent jar X in place then later same Class A compiled in different environment withe dependent jar X1 which consist new method called Y in that. now the class will be compiled because new method Y is available in jar X1 when the same Class A is used in the environment with jar X in place then it leads to the NoSuchMethod Exception when trying to load the class in the class memory. Classloader does the verification of the dependent classes before loading the class in the class memory before invoking real exceution.
Everything were available all jar files and all. After an exhausting work thinking of whats wrong, i decided to reload everything afresh (i.e reload the hadoop files). Thanks to you guys for helping :)
I am unable to run the following code in Eclipse (Eclipse IDE for Java Developers, Version: Indigo Service Release 1, Build id: 20110916-0149), and I think that I may have a configuration problem in Eclipse (but I do not know what or where):
class Saluton {
public static void main(String args[])
{
String greeting = "Saluton mondo!";
System.out.println(greeting);
}
}
I am also running against Java 6 (1.6.0_29-b11-402) on Macintosh 10.7.2.
When I run this, I get the error:
"java selection does not contain a main type"
but I am pretty sure that my class is written correctly...? I have looked this error up, and cannot explain this problem so far.
TIA for any thoughts or opinions!
I think you have to make your class public, otherwise it won't work?
EDIT: My previous answer was incorrect. The JLS says you can declare arrays with the brackets at either end. See here for some examples. My mistake.
Have you verified your configuration in Eclipse such that it knows where to find the Java compiler, and a JVM? You can check the project-specific libraries by right clicking the project and going to Properties, Java Build Path
You can also check the JRE's installed by clicking Window, Preferences, Java, Installed JREs. Make sure the JRE you wish to use is listed here and that the path is correct.
Another solution (simple and direct):
In Eclipse: File -> Restart
Right click your class Saluton and choose Run as --> Java Application.
It should work.
Ok, so I'm a fellow noob, and I came here because I had this problem. I checked all my class paths and everything, and they were correct. I had actually been putting all of my files in the JRE System Library Folder, instead of the source folder. I'm not sure if this was you'r problem, but it seemed to work for me when I moved the code files into the src folder.
I took the long way around to solve this; eventually I created a package within my project and added my source code to that package and it compiled and ran! I am learning that Wizards rule!
It will work if you make your class as public !