Debugging external libraries, without modifying them, under tomcat - java

We have a web application which sometimes (quite rarely, several times a day) gives an
error in production. It is deployed on Tomcat, uses Spring+Hibernate, the error is caused
by a Hibernate exception which is hard to understand without actually logging the
parameters passed to the method of the Hibernate class. It is not possible to replace
the Hibernate library with a modified version which logs the parameters, and spring-aop
cannot be used since the "beans" are not managed. I have seen an example of byte code
instrumentation using javassist, on http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html, however trying to run it under
tomcat, the instrumented code does not seem to run, probably due to classloader problems
which I currently don't understand.
What I am asking then, is this: does anyone know of a more or less simple way to instrument
the byte code under tomcat for such a task as logging the parameters of methods in
external libraries? is there some further insight you may give on this problem?

Have a look at BTrace.
It will allow you to log calls to other classes/functions without slowing down the main application.

You could (temporarily) enable JDWP on the production Tomcat, attach a debugger, and place a breakpoint on the offending code. But I'd recommend avoiding doing that on the actual production machine -- better to clone the production environment to another machine that you can tinker with.

Related

Reflections on tomcat server from the outside

As part of a challenge, I would like to use reflections to get information about the code running on a tomcat server as *.jsp. (Assuming that the server is not configured very secure and allows this).
Google shows absolutely no answer regarding tomcat and reflections from the outside.
I guess I might have to combine it with Remote Procedure Calls or sth like that. Any ideas?
You don't get free exploits just because Java has reflection.
Reflection (as in java.lang.reflect.*) works only from the inside. Code executing in a JVM process can reason about other code running in the same context, IOW, the program can reflect about itself.
You would need to be able to inject your spying code into the server's java process.
Luckily, servers generally don't allow you to do that, not even badly configured ones - unless there is a remote code execution vulnerability like CVE-2013-4444 for example.
You also can't abuse Remote Procedure Calls that easy. First of all, a remotely callable procedure must be placed there by the programmer. And there are none by default. But assuming you find something that is for some reason unprotected, you'd still only be allowed to call that procedure, not arbitrary code of your choice. If you can, you've probably found a vulnerability.

java.lang.StackOverflowError when parsing Groovy script on Jenkins

We are experiencing a problem with our Jenkins CI server.
Our CI implementation relies on several Groovy scripts, which we execute in Jenkins as "System Groovy scripts". This has been this way for years, and the scripts have undergone no recent modifications, and implement build flows, business logic steps such as version checking, etc.
Yesterday we started experiencing an exception in every Jenkins job that we tried to lauch that, one way or another, tried to execute Groovy scripts. The exception is:
java.lang.StackOverflowError
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.additiveExpression(GroovyRecognizer.java:12478)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.shiftExpression(GroovyRecognizer.java:9695)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.relationalExpression(GroovyRecognizer.java:12383)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.equalityExpression(GroovyRecognizer.java:12307)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.regexExpression(GroovyRecognizer.java:12255)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.andExpression(GroovyRecognizer.java:12223)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.exclusiveOrExpression(GroovyRecognizer.java:12191)
hundreds of similar lines
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.compoundStatement(GroovyRecognizer.java:7510)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.compatibleBodyStatement(GroovyRecognizer.java:8834)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.statement(GroovyRecognizer.java:899)
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.compilationUnit(GroovyRecognizer.java:757)
at org.codehaus.groovy.antlr.AntlrParserPlugin.transformCSTIntoAST(AntlrParserPlugin.java:131)
at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:108)
at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:236)
at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:161)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:846)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:550)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:526)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:503)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:302)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:281)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:731)
at groovy.lang.GroovyShell.parse(GroovyShell.java:743)
at groovy.lang.GroovyShell.parse(GroovyShell.java:770)
at groovy.lang.GroovyShell.parse(GroovyShell.java:761)
at groovy.lang.GroovyShell$parse.call(Unknown Source)
at com.cloudbees.plugins.flow.FlowDSL.executeFlowScript(FlowDSL.groovy:80)
at com.cloudbees.plugins.flow.FlowRun$FlyweightTaskRunnerImpl.run(FlowRun.java:219)
at hudson.model.Run.execute(Run.java:1759)
at com.cloudbees.plugins.flow.FlowRun.run(FlowRun.java:155)
at hudson.model.ResourceController.execute(ResourceController.java:89)
at hudson.model.Executor.run(Executor.java:240)
at hudson.model.OneOffExecutor.run(OneOffExecutor.java:43)
This looks like that the Groovy parser inside Jenkins is reaching the top of the stack while trying to parse the groovy script (as I have said, this abruptly started to happen with many scripts that worked perfectly before and had undergone no recent modification).
Currently our Jenkins installation (v1.594) runs on a Websphere 8.5.5.2 application server on AIX v7.1 (don't know exactly the fix pack level and / or if it has recently suffered any kind of update, still trying to gather the info).
After a restart, we returned to normal behavior (all the scripts were working as usual again without any modification to them).
Does anyone know about some incompatibility of any underlying library with Jenkins Groovy parsing?
There is a problem with the groovy code; causing the parser to go nuts:
java.lang.StackOverflowError
at org.codehaus.groovy.antlr.parser.GroovyRecognizer.additiveExpression(GroovyRecognizer.java:12478)
Based on a similar ticket:
https://issues.apache.org/jira/browse/GROOVY-1783,
it is possible that your code has circular references; or creating too many functions on the fly. You can take the approach of analyzing your code and trying to put anything that is going to make allocations outside of loops; in particular complex inline functions.
Another approach is to go look at the Build Flow plugin and scroll down the documentation and see how you could write an extension point rather than use groovy. This may not be easy to do and requires effort; but you can write a lot of tests for your code that way. You would still use groovy for the glue; but use java directly for the hot spots.
A third approach would be to file a ticket on the Groovy issue tracker; and see what the experts find out.

Methods to see result fo a code change faster

This question came to me when developing using Eclipse.
I use JBoss Application Server and use hot code replacement. But this option requires that the 'build automatically' option to be enabled. This makes Eclipse build the workspace automatically (periodically or when a file is saved?) and for a large code base this takes too much time and processing which makes the machine freeze for a while. Also sometimes an error message is shown saying that hot code replacement failed.
The question that I have is: is there a better way to see the result of a code change?
Currently I have the following two suggestions:
Have unit tests - this will allow to run a single test and see the result of a code change. ( But for a JavaEE application that uses EJBs is it easy to setup unit tests?)
Use OSGi - which allows to add jars to the running system without bringing down the JVM.
Any ideas on above suggestions or any other suggestion or a framework that allows to do this is welcome.
Did you take a look at http://zeroturnaround.com/jrebel/?
I tell you how I work. I hope it is useful. First of all, I disable "Build Automatically". Maybe it is better if you do a simple ANT script to compile and see errors/exceptions. Also, I make jar file with the same script. Afterwards, I use OSGi to check the application. Yo do not need to stop server, only you need to change versions in deployed bundles. Intead of JBoss Server I use Equinox which includes Jetty Web Server.
May you have a nice day!
With JRebel, you wouldn't have to build your project (skip the build totally). Plus, only the changed resources will be reloaded so the update happens instantly. Plus, session is preserved so you do not have re-login to the application after the update was performed.
Even though the question I asked was quite specific to Java, I thought that mentioning using an interpreted programming language that avoids the compilation step is anther way of seeing result of a code change faster.

Java project with executable jars; running and retrieving data from them

At work, I use a Java application (I have located compiled/executable jars on the C-drive). I want to be able to grab some information from this application through code. The application itself probably does not store information, so it must communicate with legacy systems some way, I am not sure how, I have seen traces of a Servlet(?) Hence, I suspect the application also has built-in "encryption"(?)
I do not want to get involved in encryption and login procedures etc., so I am thinking I could just build a Java project around the current executable jars, and launch the application as I usually do (through the "main" entry point, "Start.jar", but then after execution call the functions that I want to (i.e. the application just runs as usual in the background)...
Would that be possible? Is there another way? Can one, for example, hook up to an already executed Java application and issue commands?
What I have tried so far
Downloaded Eclipse, and created a new project
Made Eclipse "reference" external jars (there was a wizard in Eclipse)
Created a new class in my new project, in which I launch the "main" entry point of the "main" executable jar (the structure of all the jars pops up with "IntelliSense"). I have also found out which argument I need to supply to the main procedure using JD-GUI (Java Decompiler)...
It seems that from inside the main procedure a call is made to another procedure, which resides in a different jar, in the debug window of Eclipse I just see an error, which made me doubt that my current approach is viable... Maybe the problem arises because the command is issued from a compiled jar? Could there be an issue with the "class path"? Does this at all seem like a solution? But then again, I have no experience with Java (mostly VBA and some C#).
You can start your JVM for the application with options, which enable remote debugging. Then you can connect the eclipse debugger to this JVM.
http://www.eclipsezone.com/eclipse/forums/t53459.html
Based on your question, I am going to guess that your application does not have a Java API you can code against. That would, of course, be the easiest way. So, if you have not checked, do that first.
Assuming you don't have an API to code against, I think your approach is correct. But it could be hard to do, since you are basically flying blind trying to figure out what the application is doing. Remote debugging might solve part of that problem.
There might be a slightly easier solution, if you are sure it is sending requests across the network. You can use a tool like Wireshark to see what it is creating. Then, you can have your application create requests that look like that and send them to that destination. This assumes of course that the requests aren't encrypted. In that case you are probably out of luck.

How to compile single/multiple java files without server restart? Is there any Eclipse plugin for the same?

I want to compile multiple java files in my Application without restarting Weblogic and Tomcat. Otherwise, this takes a lot of time. For this I got one Hotswap plugin in Eclipse, but this is not working in all the cases. It says it works for single file compile. Even if I use that it is not working in all the cases.
Is there any other way that I can do this or is there any other plugin/script/software which can help me in this?
If there are some open source ones, it will be very helpful.
Thanks in Advance.
One thing is compiling the classes, but you also need the JAVA VM to reload the classes and use them, which is called hot-swapping. For the best available hot-swapping of classes you'll need something like javarebel. It allows you to hot-reload a lot more types of code-changes than the regular SUN JVM. If you run your deployment in exploded-mode you're home free, and can test any code change in a second or so. We're fairly test-driven, so I only use javarebel in that short phase when I assemble the whole application, but it works really well.
The Java HotSpot VM does this automatically, but not in all cases...
First, you must be running a "debug" session, not a "run" session.
Next, some changes will force a restart. The basic idea is that if the interface to the class change (the method sigs, not an actual Java interface), the VM can't replace the class contents inline.
You shouldn't need a plugin for this, just a recent-ish VM.
This happens under several circumstances like
adding methods
removing methods
changing method signatures
changing the class hierarchy (superclasses, implemented interfaces)
It can also happen if you introduce an error into the class. (For errors like mismatched curly braces)
When you save a Java file, eclipse compiles it. If there is an error, eclipse inserts an exception throw to indicate that there is an unresolved compilation error. (It does this so when you run you don't just see the last successful compilation, making it obvious you have a compiler error)
I don't know Eclipse, but I do use Netbeans. Netbeans does this pretty well. The latest version even has an option to automatically recompile when you save a java file.
I know this doesn't exactly answer your question. You can probably use both Netbeans and Eclipse depending on what part of the project you're working on.
EDIT:
With Tomcat you can reload the web app. This is really only useful if Tomcat is looking at the new class. If your project is compiled to a build directory first and a WAR is then created from this you can go into Tomcat and install the web app and instead of pointing at a WAR point at the build directory.
In Tomcat you may have to put a site config file under tomcat/conf/Catalina/localhost. The contents of this file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="C:/Projects/MyWebApp/build/web" path="/MyWebApp"/>
Instructions for reloading here:
http://www.cs.ucl.ac.uk/teaching/java/tomcatfaq.html#changeservlet
If you do this a few times though Tomcat will run out of memory. This is because of something called PermGenSpace. Read up about it if you want to know more. The solution is to increase the JVM memory, the PermGenSize (with -XX:MaxPermSize) and finally restarting Tomcat occasionally.
EDIT2:
If reloading the app causes you to be logged out you may be able to easily get the container to serialize your session data to disk by adding 'implements Serializable' to some of your classes. Then you should not need to login after reloading the app.
I agree that it is very tedious to redeploy all the time when developing.
I would suggest you look into MyEclipse which has a very good hotdeploy mechanism which works well with Tomcat, and which is quite affordable and has a 30 day trial.
The stock Java EE mechanism in Eclipse for redeploying to servers is nowhere as fast.
I guess I don't really see where the problem is. Here is what I do and the changes load almost instantaneously. I have an Ant script that compiles the .java and .jsp files for me, puts them in the appropriate directories under webapps and changes the web.xml file if necessary (or at least touches it to notify tomcat of the changes). If you need help on doing any of that with Ant, I'd be happy to help. Btw I do not use WAR files for deployment on my testing machine. That would be a lot slower I guess.
very easily done if you read this page:
See http://blog.redfin.com/devblog/2009/09/how_to_set_up_hot_code_replacement_with_tomcat_and_eclipse.html
Thank you Dan Fabulich

Categories