This question already has answers here:
Eclipse java debugging: source not found
(33 answers)
Closed 9 years ago.
While debugging a relatively small program in Eclipse, I am seeing "Source not found" errors as I step through. Other questions state that this is usually an import/jar problem. In this case, I have no imported jar files, nothing fancy, just classes in the src/default package.
The specific behavior is this:
If the debugger is pointed at a line which instantiates a new object (e.g., "Foo foo = new Foo();") where the class, Foo, in question is in the same source directory and has a valid constructor, one of two things happens:
1) Either: Hitting F5 will take me into the class and onto the constructor signature; a subsequent F5 will take me to the dreaded "Source Not Found" error;
2) Or: Hitting F5 will take me immediately to the "Source Not Found" error
In either case, I can continue the debugging.... sort of. E.g., the debug session continues and stepping forward results in further steps through the program. (If I run this program without the debugger, or if there are no breakpoints at those locations, I see no problems. Hitting F8 and going to the next breakpoint will usually get me free of the problem.)
The Java Build Path source is set correctly (the src subdirectory of the project, which is where the default package is sitting.) The Java Build Path libraries has nothing but the JRE System Library, and as far as I know there are no name clashes. I can't think of anything else I'd need to do to the Java Build Path.
This is probably not related to the bug I am hunting with the debugger (NaN proliferation in numerical application) but it is distracting, and it is hampering my ability to get to the root of the problem.
Specific question: What is causing this behavior? Or is it expected behavior that I have not noticed before?
EDIT: Including Code
Loop2: for (int depth = 0; depth < maxDepth; depth++) {
for (int node = 0; node < policy.numMemory; node++) {
Belief belief = new Belief(messages, node);
nodeTraces[node] = new nodeTrace(policy, pomdp, messages, belief, depth);
if (nodeTraces[node].bestGain > bestGain) {bestTrace = node; bestGain = nodeTraces[node].bestGain; }
}
if (bestGain > 0.01) { System.out.println("breaking"); break Loop2; }
}
Setting a breakpoint at Belief belief = new Belief(messages, node); above, and hitting F5 will yield the Source Not Found message in the debugger. A code snippet from that class is:
public class Belief {
int numStates;
double[] belief;
public Belief(Messages messages, int node) {
// do some stuff
}
I stress again that there are no included packages anywhere in this project. All classes are mine and reside in the project's own source directory, which is included in the Java Build Path's source tab. If the suggested link above explains what it going on here, I am just not seeing it even after reading it three times, and I will be grateful if someone explains it to me in small words.
Eclipse may be missing the source of the standard library, i.e. the JDK.
This can be set via Preferences -> Java -> Installed JRE .
Related
Little background for context:
The application I support allows third parties to develop plugins that can leverage some of our functionality. We hand them our "externalAPI.jar"; they put it in their project, implement some interfaces, and build their own APK. We find the would-be plugin by asking the package manager for all installed applications and see if each has a "pluginclass.xml" in the assets directory. If it has that XML file, we anticipate its contents being the canonical path of a class that implements our ExternalPluginVX interface, and using a new PathClassLoader(ApplicationInfo.sourceDir, this.getClass().getClassLoader()), we load the class, create a new instance, and start using it.
The problem:
Sometimes third parties will put
compile files ("./libs/externalAPI.jar")
in their gradle files instead of the correct syntax:
provided files ("./libs/externalAPI.jar")
The result of course being things don't work properly. Sometimes they almost work, but then have unpredictability in their behavior - usually involving vicious crashes. Notably, since their APK is well-formed in its own right, and the XML file is there, we'll see the plugin, load the target class successfully, instantiate it successfully, and things go haywire from there when they try and reference back to us.
The question:
Is there a way for my application to check at runtime if the other application compiled our API classes into their APK instead of using provided files like they should have?
A viable solution is to use a DexFile.
Since I already have the ApplicationInfo.sourceDir, I can just construct a DexFile and iterate through its contents.
//this variable's value assigned by iterating through context.getPackageManager().getInstalledApplications(0)
ApplicationInfo pkg;
String interfaceTheyShouldntHave = ExternalPluginVX.class.getCanonicalName(); //"com.project.external.ExternalPluginVX"
DexFile dexFile = new DexFile(pkg.sourceDir);
Enumeration<String> entries = dexFile.entries();
while(entries.hasMoreElements()){
String entry = entries.nextElement();
if(entry.equals(interfaceTheyShouldntHave)){
Toast.makeText(ctxt, "Plugin \"" + pluginName + "\" could not be loaded. Please use 'provided files' instead of 'compile files'", Toast.LENGTH_LONG).show();
return;
}
}
I am not sure why is it giving this error. Braces seem to be right. Another thing is that the same program works in Windows-eclipse but not in eclipse for Mac. What could be the reason?
import java.util.Vector;
public class Debug
{
private int something = 0;
private Vector list = new Vector();
public void firstMethod()
{
thirdMethod(something);
something = something + 1;
}
public void secondMethod()
{
thirdMethod(something);
something = something + 2;
}
public void thirdMethod(int value)
{
something = something + value;
}
public static void main(String[] args)
{
Debug debug = new Debug();
debug.firstMethod();
debug.secondMethod();
}
}
Ah, ok - it's probably a control-Z or other unprintable character at the end of the file that is ignored in Windows but not on the Mac. You copied the source from Windows to the Mac. Delete the last few characters and re-enter them - I think it will go away. I don't do Mac, though - I'm just guessing.
I had the same problem importing my projects from mac to linux Slackware.
Mac OSX creates some temporary files with the same name of the files in folders (._filename) in all folders.
Usually these files are invisible in Mac OSX, but in the other OSs no.
Eclipse can find these files and tries to handle like sources (._filename.java).
I solved deleting these files.
Only way i could resolve this problem was press Ctrl+A to select all text of file then Ctrl+C to copy them then delete file and create new class with intellij idea then Ctrl+P to paste text in new file. this resolve my problem and compiler never show error after do this solution.
It can happen when we copy and paste .It happens when there may be some character which is unrecognized in one platform but recognized in other.
I would suggest don't copy rather try to write the entire code by yourself. It should work
I got the same error when I imported a project I created in a Mac, to Windows. As #Massimo says Mac creates ._filename,java files which eclipse running in windows consider as source files. This is what causes the problem.
They are hidden files, which you can see when you select the option, "Show hidden files and folders" under folder options in Windows machine. Deleting these files solves the problem.
I got this message trying to call a subjob from a tRunJob component. In the tRunJob I had both checked "transmit whole context" AND listed individual parameters in the parameters/values box. Once I removed the additional parameters it worked.
There are probably hidden characters in the line. If you move your cursor through the characters and your cursor doesn't move in one character, that means there is an invalid character in the line. Delete those and it should work. Also try copying and pasting the line to an hex editor and you will see the invalid characters in it.
i face this problem many times in eclipse . What i found is that select all code - cut it using Ctrl + x and then save the file and again paste the code using Ctrl + V . This works for me many times when i copy the code from another editor.
I also faced similar issue while copying the code from one machine to another.
The issue was with Space only you need to identify the red mark in your eclipse code.
On Windows, if you copy the source to Notepad - save the file (as anything), ensuring ASCI encoding is selected - the character will be converted to a question-mark which you can then delete - then copy the code back to Eclipse.
In eclipse right click on the file -> Properties -> resources
In Text file encoding select US-ASCII
This way you will see all the special char, you can then find & replace
And then format the code
this has been a crappy day, besides the IDE not compiling/deploying because of this bug and waisting valuable time, I finally get it to deploy it suddenly I start getting this weird message (after compiling and running it several times):
T:\Users\Triztian\Documents\RHT System\RHTUBSDB\src\java\controllers\OrderSearch.java:64: cannot find symbol
symbol : method metadata(java.lang.Long)
location: class BO.CoverForm
OrderExtraInfoDTO foundInformation = frmCover.metadata(foundOrder.getReferenceNumber());
it is my understanding that this means that my method isn't declared, but thats not the situation as my method is clearly declared and coded.
CoverForm.java:
public OrderExtraInfoDTO metadata(Long ReferenceNumber) {
OrderExtraInfoDTO foundInformation = new OrderExtraInfoDTO();
try{
foundInformation = lnkAddInformation.fetchInformation(ReferenceNumber);
} catch (DAOException daoe) {
this.setError("additional_information", daoe.getMessage());
}
return foundInformation;
}
And the servlet that calls the CoverForm.java method.
OrderSearch.java (Extends HttpServlet):
CoverDTO foundCover = frmCover.search(foundOrder.getReferenceNumber());
OrderExtraInfoDTO foundInformation = frmCover.metadata(foundOrder.getReferenceNumber());
UpgradesDTO foundUpgrades = frmUpgrades.search(foundOrder.getReferenceNumber());
I've tried renaming the method and didn't have any success, any help is truly appreciated as I'm getting frustrated with NB 6.9.1 because of some crashes and another weird bug (might catch an entomologist's attention) which locks the editor and displays a message saying: "Refactoring cannot be done in the given context" whenever I press delete, forcing me to restart the IDE.
EDIT
Ok, so I've removed the classes that I posted and merged them in a more appropriate place, however I still get that silly symbol not found error but on a different symbol(another method) this time.
Netbeans 6.9.1 is a very robust IDE. You may run into problems like the one you mention above, if:
You run your NB without enough disk space available. Make sure that you have at least 2 GB free on your file system for the necessary temporary files.
You have a very large number of projects active in your project space. Reduce this number to just the needed projects, by deleting and reopening more often.
Hope this helps ...
I know. Heresy. But I'm in a bind. I have a lot of config files that use absolute path names, which creates an incompatibility between OS X and Windows. If I can get OS X (which I'm betting is the more flexible of the two) to recognize Q:/foo/bar/bim.properties as a valid absolute file name, it'll save me days of work spelunking through stack traces and config files.
In the end, I need this bit of Java test code to print "SUCCESS!" when it runs:
import java.io.*;
class DriveLetterTest {
static public void main(String... args) {
File f = new File("S:");
if (f.isDirectory()) {
System.out.println("SUCCESS!");
} else {
System.out.println("FAIL!");
}
}
}
Anyone know how this can be done?
UPDATE: Thanks for all the feedback, everyone. It's now obvious to me I really should have been clearer in my question.
Both the config files and the code that uses them belong to a third-party package I cannot change. (Well, I can change them, but that means incurring an ongoing maintenance load, which I want to avoid if at all possible.)
I'm in complete agreement with all of you who are appalled by this state of affairs. But the fact remains: I can't change the third-party code, and I really want to avoid forking the config files.
Short answer: No.
Long answer: For Java you should use System.getProperties(XXX).
Then you can load a Properties file or Configuration based on what you find in os.name.
Alternate Solution just strip off the S: when you read the existing configuration files on non-Windows machines and replace them with the appropriate things.
Opinion: Personally I would bite the bullet and deal with the technical debt now, fix all the configuration files at build time when the deployment for OSX is built and be done with it.
public class WhichOS
{
public static void main(final String[] args)
{
System.out.format("System.getProperty(\"os.name\") = %s\n", System.getProperty("os.name"));
System.out.format("System.getProperty(\"os.arch\") = %s\n", System.getProperty("os.arch"));
System.out.format("System.getProperty(\"os.version\") = %s\n", System.getProperty("os.version"));
}
}
the output on my iMac is:
System.getProperty("os.name") = Mac OS X
System.getProperty("os.arch") = x86_64
System.getProperty("os.version") = 10.6.4
Honestly, don't hard-code absolute paths in a program, even for a single-platform app. Do the correct thing.
The following is my wrong solution, saved to remind myself not to repeat giving a misdirected advice ... shame on me.
Just create a symbolic link named Q: just at the root directory / to / itself.
$ cd /
$ ln -s / Q:
$ ln -s / S:
You might need to use sudo. Then, at the start of your program, just chdir to /.
If you don't want Q: and S: to show up in the Finder, perform
$ /Developer/Tools/SetFile -P -a V Q:
$ /Developer/Tools/SetFile -P -a V S:
which set the invisible-to-the-Finder bit of the files.
The only way you can replace java.io.File is to replace that class in rt.jar.
I don't recommend that, but the best way to do this is to grab a bsd-port of the OpenJDK code, make necessary changes, build it and redistribute the binary with your project. Write a shell script to use your own java binary and not the built-in one.
PS. Just change your config files! Practice your regex skills and save yourself a lot of time.
If you are not willing to change your config file per OS, what are they for in first place?
Every installation should have its own set of config files and use it accordingly.
But if you insist.. you just have to detect the OS version and if is not Windows, ignore the letter:
Something along the lines:
boolean isWindows = System.getProperty("os.name").toLowerCase()
.contains("windows");
String folder = "S:";
if (isWindows && folder.matches("\\w:")) {
folder = "/";
} else if (isWindows && folder.matches("\\w:.+")) {
folder = folder.substring(2);// ignoring the first two letters S:
}
You get the idea
Most likely you'd have to provide a different java.io.File implementation that can parse out the file paths correctly, maybe there's one someone already made.
The real solution is to put this kind of stuff (hard-coded file paths) in configuration files and not in the source code.
Just tested something out, and discovered something interesting: In Windows, if the current directory is on the same logical volume (i.e. root is the same drive letter), you can leave off the drive letter when using a path. So you could just trim off all those drive letters and colons and you should be fine as long as you aren't using paths to items on different disks.
Here's what I finally ended up doing:
I downloaded the source code for the java.io package, and tweaked the code for java.io.File to look for path names that start with a letter and a colon. If it finds one, it prepends "/Volumes/" to the path name, coughs a warning into System.err, then continues as normal.
I've added symlinks under /Volumes to the "drives" I need mapped, so I have:
/Volumes/S:
/Volumes/Q:
I put it into its own jar, and put that jar at the front of the classpath for this project only. This way, the hack affects only me, and only this project.
Net result: java.io.File sees a path like "S:/bling.properties", and then checks the OS. If the OS is OS X, it prepends "/Volumes/", and looks for a file in /Volumes/S:/bling.properties, which is fine, because it can just follow the symlink.
Yeah, it's ugly as hell. But it gets the job done for today.
I have an application which is running on tomcat, one of the methods is, creating a simple thumbnail from an jpeg image. The functions works fine offline and a week ago also on tomcat. But now i get the following error:
java.lang.NoClassDefFoundError
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:164)
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68)
java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1141)
eval.impl.ImageEval.getThumbnail(ImageEval.java:155)
eval.impl.ImageServlet.doGet(ImageServlet.java:79)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
I don't think that i have change anything what should influence this (actually i didn't change the function at all according to the svn repository), so it must be a library problem. But i can't figure out what is missing.
Here are the actual lines from the getThumbnail function, where the error occures:
BufferedImage thumbImage = new BufferedImage(thumbWidth,
thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(simage, 0, 0, thumbWidth, thumbHeight, null);
[edit] I decided to update the problem description a little.
Yes it seems that he can not find some class from java.awt or one related to that. But they do exist on the server in the jvm. Java headless mode doesn't solve the problem.
In another project the exact same code, but inside an axis2 webservice on this server is working fine.
[/edit]
It seems like you've change the configuration of Tomcat.
Either you've changed to a l{0,1}[iu]n[iu]x box or installed on a virtual machine with different security control than the one where you test it.
Apparently the
GraphicsEnvironment.getLocalGraphicsEnvironment()
Is trying to access the property: java.awt.graphicsenv
Which may return null or some non existing class name which is then loaded and throws the ClassNotFoundException. 1
The solution seems to be specifying the "java.awt.headless" property.
This is a similar question: java.awt.Color error
Try this search , it shows similar situations as your.
I remember there was something in the sun bugs database too.
Post the solution when you find it!
1.GraphicsEnvironment.java
EDIT
It is not eclipse!!
In my original post there is a link to the source code of the class which is throwing the exception.
Since I looks like you miss it, I'll post it here for you:
public static synchronized GraphicsEnvironment getLocalGraphicsEnvironment() {
if (localEnv == null) {
// Y O U R E R R O R O R I G I N A T E S H E R E !!!
String nm = (String) java.security.AccessController.doPrivileged
(new sun.security.action.GetPropertyAction
("java.awt.graphicsenv", null));
try {
// long t0 = System.currentTimeMillis();
localEnv =
(GraphicsEnvironment) Class.forName(nm).newInstance();
// long t1 = System.currentTimeMillis();
// System.out.println("GE creation took " + (t1-t0)+ "ms.");
if (isHeadless()) {
localEnv = new HeadlessGraphicsEnvironment(localEnv);
}
} catch (ClassNotFoundException e) {
throw new Error("Could not find class: "+nm);
} catch (InstantiationException e) {
throw new Error("Could not instantiate Graphics Environment: "
+ nm);
} catch (IllegalAccessException e) {
throw new Error ("Could not access Graphics Environment: "
+ nm);
}
}
return localEnv;
}
That's what gets executed.
And in the original post which you don't seem to have read, I said the code is accessing the property "java.awt.graphicsenv"
If that other project using axis doesn't have the same problem it may be because it may be running in a different tomcat configuration or the axis library allowed the access to that property. But we cannot be sure. That's pure speculation. So why don't you test the following and see what gets printed:
String nm = (String) java.security.AccessController.doPrivileged
(new sun.security.action.GetPropertyAction
("java.awt.graphicsenv", null));
System.out.println("java.awt.graphicsenv = " + nm );
It it prints null then you now what the problem is. You don't have that property in your system, or the security forbids you do use it.
It is very hard to tell you from here: "Go and edit file xyz and add : fail = false" So you have to do your work and try to figure out what's the real reason.
Start by researching what's the code being executed is ( which I have just posted ) and follow by understand what it does and how does all that "AccessController.doPrivileged" works. (You may use Google + StackOverflow for that).
We had a similar issue and after much trouble shooting it was identified to be related to the java.awt.headless property. The issue was resolved by explicitly setting the JVM option to
-Djava.awt.headless=true
It was running a week ago, and now it is not.
THEREFORE, YOU CHANGED SOMETHING BETWEEN "working" and "not working".
Go back to the working config (if you can), and rigorously track what you changed. If you don't have a backup of the working config, then meticulously go back through what you've done between working and non-working until you find what you changed.
It may not be code - it could be a config file, etc.
Best of luck,
-R
Is this server running java in server mode - I hear that doesn't load in the AWT classes.
If you are deploying this on *nix, and you don't have an X window system running anymore, that could explain it. Even if you do, if you aren't exporting the DISPLAY system variable to the process that starts the JVM, or if you are but it is not actually valid, it could cause such an issue.
That would at least explain why you didn't change any configuration in tomcat, but still have a problem.
If your NoClassDefFoundError has no message at all, then this means two things:
The JVM has already tried and failed to load a class. Usually, this means the JVM was unable to complete static initialization for that class, i.e. assign values to any static fields and run any static { } blocks. Often, this is because the classes necessary to do this static initialization are missing.
You're using Java 5, not Java 6. (In Java 6, you get a 'Could not initialize class xyz' message instead.)
The problem class appears to be the one whose name is the value of the system property java.awt.graphicsenv. I would start by finding out the value of this property. What happens when you try to instantiate this class?
Since you're getting NoClassDefFoundError from inside the AWT code, it looks like Java is failing to load the X Windows libraries. Note that even if you're running in headless mode ($DISPLAY not pointing to an X Windows server), AWT still needs some subset of the X11 libraries in order to render images. See, for example, this reference:
http://javatechniques.com/blog/linux-x11-libraries-for-headless-mode
If something stopped working and your Java code didn't change, it's possible that the X11 libraries got moved or uninstalled on your machine, or that for some other reason your LD_LIBRARY_PATH environment variable doesn't point to them anymore.