NoClassDefFoundError while accessing GraphicsEnvironment.getLocalGraphicsEnvironment on Tomcat - java

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.

Related

Getting a specific version of an image with Jib (Maven, Docker, testcontainers)

I'm trying to understand a comment that a colleague made. We're using testcontainers to create a fixture:
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
public class SalesforceFixture extends GenericContainer<SalesforceFixture> {
private static final String APPLICATION_NAME = "salesforce-emulator";
public SalesforceFixture() {
// super(ImageResolver.resolve(APPLICATION_NAME));
super(DockerImageName.parse("gcr.io/ad-selfserve/salesforce-emulator:latest"));
...
}
...
The commented code is what it used to be. The next line is my colleague's suggestion. And on that line he commented:
This is the part I don't know. The [ImageResolver] gets the specific version of the emulator, rather than the latest. You need a docker-info file for that though, which jib doesn't automatically generate (but I think it can).
This is what I know or have figured so far:
SalesforceFixture is a class that will be used by other projects to write tests. It spins up a container in Docker, running a service that emulates the real service's API. It's like a local version of the service that behaves enough like the real thing that if one writes code and tests using the fixture, it should work the same in production. (This is where my knowledge ends.)
I looked into ImageResolver—it seems to be a class we wrote that searches a filesystem for something:
public static String resolve(String applicationName, File... roots) {
Stream<File> searchPaths = Arrays.stream(roots).flatMap((value) -> {
return Stream.of(new File(value, "../" + applicationName), new File(value, applicationName));
});
Optional<File> buildFile = searchPaths.flatMap((searchFile) -> {
if (searchFile.exists()) {
File imageFile = new File(searchFile + File.separator + "/target/docker/image-name");
if (imageFile.exists()) {
return Stream.of(imageFile);
}
}
return Stream.empty();
}).findAny();
InputStream build = (InputStream)buildFile.map(ImageResolver::fileStream).orElseGet(() -> {
return searchClasspath(applicationName);
});
if (build != null) {
try {
return IOUtils.toString(build, Charset.defaultCharset()).trim();
} catch (IOException var6) {
throw new RuntimeException("An exception has occurred while reading build file", var6);
}
} else {
throw new RuntimeException("Could not resolve target image for application: " + applicationName);
}
}
But I'm confused. What filesystem? Like, what is the present working directory? My local computer, wherever I ran the Java program from? Or is this from within some container? (I don't think so.) Or maybe the directory structure inside a .jar file? Or somewhere in gcr.io?
What does he mean about a "specific version number" vs. "latest"? I mean, when I build this project, whatever it built is all I have. Isn't that equivalent to "latest"? In what case would an older version of an image be present? (That's what made me think of gcr.io.)
Or, does he mean, that in the project using this project's image, one will not be able to specify a version via Maven/pom.xml—it will always spin up the latest.
Sorry this is long, just trying to "show my work." Any hints welcome. I'll keep looking.
I can't comment on specifics of your own internal implementations, but ImageResolver seems to work on your local filesystem, e.g. it looks into your target/ directory and also touches the classpath. I can imagine this code was just written for resolving an actual image name (not an image), since it also returns a String.
Regarding latest, using a latest tag for a Docker image is generally considered an anti-pattern, so likely your colleague is commenting about this. Here is a random article from the web explaining some of the issues with latest tag:
https://vsupalov.com/docker-latest-tag/
Besides, I don't understand why you ask these questions which are very specific to your project here on SO rather than asking your colleague.

javassist - How can I replace a method body without extra startup flags on Java 17?

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?

Java, Eclipse, "Source Not Found" [duplicate]

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 .

Another Netbeans issue | cannot find symbol method, but correctly declared

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 ...

Java clip.play hangs on 3rd invocation

I'm running a java (Netbeans) application on Ubuntu 10.10. The following code plays the sound correctly the first two times it is invoked. On the third invocation, the application hangs and I have to kill the process. Any ideas?
try {
String path = ApplicationContext.getInstance().getAppDirectory();
java.net.URL url = new java.net.URL("file:"+path+"my.wav");
java.applet.AudioClip clip = java.applet.Applet.newAudioClip(url);
clip.play( );
}catch (java.net.MalformedURLException malex){
Logger.log(malex);
}
No exception or error is reported.
debugging with strace was getting really complex. I ended up taking the easy way out. Here's my solution:
java.io.InputStream in = new java.io.FileInputStream(path+"my.wav");
sun.audio.AudioStream as = new sun.audio.AudioStream(in);
sun.audio.AudioPlayer.player.start(as);
Unfortunately, this is not a good solution because:
warning: sun.audio.AudioStream is internal proprietary API and may be removed in a future release.

Categories

Resources