Thursday, September 24, 2009

Modify javap to output to String, view decompiled information at runtime.

I asked the following question on Stackoverflow:

"I am working with an application webserver and have complicated classloading issues. I want to be able to download or print information that would normally get printed by javap (the methods, etc).
I may also need to get the raw binary class data, to perform a binary diff.
How would you do this?"

I was not satisfied with the responses from stack. Sure, I could have used reflection to print information on a particular class from the web, but I was looking for the output from javap.

Javap is essentially a decompiler that comes with Sun's set of Java tools, it is used to print the method names and other information for an associated class.



It is a useful tool, how do you run the tool on code that is deployed on a server, at runtime?


It seemed obvious that javap was written in Java, so I naturally assumed that the source was available with openjdk. Source for javap is available GPL licensed in the mercurial repository. There is no use of the java.lang.Reflection API, all data collected on the class is based on the binary content of the class.

http://hg.openjdk.java.net/jdk7/jaxp/langtools/

I used the source to add small modifications to run javap in a web environment, simply converting the data to a string.



I made two major changes to extract the class information dynamically. One: return the current thread, current classloader and then find the class resource. Two: instantiate a bytearrayoutputstream object and use the outputstream to write the javap information. Then use the bytearrayoutputstream to convert the data to a string object. After performing those steps, use the string data in any environment you need to.
   
public void displayResults(InputStream classinMem) {
final InputStream classin = classinMem;
try {
// actual do display
JavapPrinter printer = new JavapPrinter(classin, out, env);
printer.print();

} catch (IllegalArgumentException exc) {
error(exc.getMessage());
}
}
public void entry(String[] argv) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.out = new PrintWriter(baos);
try {
this.perform();
} finally {
out.close();
} // End of the try - Catch Finally //
}
public void perform() {
final InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(classNameParm);
if (input == null) {
throw new IllegalStateException("Invalid class resource, classname=" + classNameParm);
}
displayResults(input);
}

Shown in the screenshot below, we get similar output as String content.



Download the Full Source
Download the source, tested with Java 1.5 compiler and runtime.

http://jvmnotebook.googlecode.com/svn/trunk/misc/javap/
http://jvmnotebook.googlecode.com/files/javap_to_string.zip

Disclaimer: I didn't have time to re-compile the code after some changes. So, you may have to make obvious edits to get all of the code to work. And the build.xml is not working.

------------------------

Thursday, September 17, 2009

Random Software Developer Thoughts - Entry Number One

I have these thoughts that pop into my head related to software. I always say I need to write these downs. Here is my first entry, writing down these thoughts. They are amazingly random, in a list format. Sometimes I may need to elaborate. I write software for a living, if you don't work in software, maybe this will help you get into the mind of a software developer.
Note: a lot of the comments are geared towards J2EE java development.

Entry Number One

  1. Software development can be very boring sometimes. Think about it, you sit in a cubicle/office eight hours a day, staring at a computer screen. For major portions of your life.
  2. Software development can be very interesting sometimes. You write software that thousands or millions or no one uses regularly. The user normally doesn't have a clue how the software gets written and there are all kinds of fixes, hacks, and easter eggs left in code. You as a developer may have minutes or hours that can effect a major release. A change that can cost millions of dollars. It kind of sucks that developers don't get good coffee.
  3. No one understands the importance of quiet. A noisy office is an unproductive office.
  4. I don't understand how git is so much better than svn. I guess Linus says so, so it must be true. Hasn't svn been used in production environments? Will git make a project better? Shrug
  5. Mac hardware is pretty nice. Mac software isn't so bad either, the software just runs
  6. Microsoft Windows software is functional. There are definitely times when Microsoft Windows XP needs to be slapped around. Why did it take 15 minutes for my machine to boot. It booted in 2 minutes a couple of months ago? Why did my software just lockup?
  7. I haven't ever seen the blue screen of death on a WindowsXP, Win2k machine.
  8. I rarely saw the blue screen of death on a Win98 machine.
  9. Linux is also functional. Distros like Ubuntu Linux could work on polishing some of the user interface, making things easier. Sure Ubuntu Linux is a lot easier than Redhat 5.0 back in the mid 90s. But is usability as easy as on Mac? Software evolves. Ubuntu Linux will get better over time. Right now, it is not amazingly great. Think about it. Is Ubuntu Linux 9.04 better than Redhat5? Yes. Will Ubuntu Linux version 20 work better than Ubuntu 9.04? Yes. Is Apple's Snow Leopard a better user experience than Ubuntu Linux 9.04? Maybe. For me it is.
  10. Eclipse IDE can suck
  11. Eclipse IDE sucks
  12. Why does Eclipse IDE take 1.5 gigs of ram to run, according to the Windows Task Manager? There is only one project.
  13. Java development can suck.
  14. Companies pay money for Java developers to write code
  15. There are a lot of companies looking for Java developers
  16. Can Java developers program?
  17. What about Python? Can they program? Are a lot of companies paying python programmers?
  18. I hate the idea of contracting. Maybe I am too lazy to convince people to personally give me money.
  19. Contractors make a lot of money
  20. Most contractors I have met aren't worth a percent of a percent what they are paid
  21. Especially Java Contractors
  22. Why are programmers so egotistical and angry (this is based on my observations on Internet forums). "How do I read a file in Java?" "You suck, go read the Java API" "Get out of here". Never heard that in ##java.
  23. I wondering if you asked "Where are the political books in a bookstore"? Would the salesperson tell you to RTFM? Would Gandhi?
  24. Lisp
  25. Common Lisp and Scheme are interesting syntactically
  26. Scala, Haskell, Clojure are interesting languages.
  27. ObjectiveC is pretty fast
  28. There are a lot of women programmers. Everywhere I have worked, the percentage has been 40%/60% female/male or 30%/70%.
  29. Yet another myth
  30. I am male, I don't see any differences in the way that womem work? Why would there be?
  31. Developers at startups are normally young.
  32. Developers at startups are young, dress like hippies and hover around major California cities.
  33. Startup developers always seem distracted and unprofessional
  34. Developers are major companies are older
  35. Is web application programming, building web systems really programming?
  36. Is making a simple configuration change, calling a Java API programming?
  37. Why does lunch for software developers always include Chinese food?
  38. Software developers are diverse, where are all the American born programmers?
  39. J2EE Application Servers are Slow.
  40. J2EE Application Servers are slow and eat up a lot of memory. Maybe that is why they are slow? Too many garbage collections. Garbage collects are slow.
  41. Public Internet service sites like google, yahoo are pretty fast. Must be heavy used of Memcache type systems.
  42. Web development can suck
  43. Java Server Pages are horrible templating systems. They allow a developer to break many fundamental programming paradigms. Do you use jsp:include? How do you structure your document? What about all of these taglibs that do the same thing? Scriptlets. We should sue Sun.
  44. There are a lot of Java frameworks out there? But not that many. There are only a dozen or so popular ones. Hibernate, Spring, JSF, Struts.
  45. Game Development with OpenGL is hard
  46. But not that difficult.
  47. I never did learn Perl but I did OK with scripting in Python
  48. Ruby Language
  49. I wonder what the software development world is like in Japan
  50. Are most software developer atheist?
  51. Isn't programming a lot easier now than 40 years ago?
  52. Bill Gates helped work on Microsoft Basic
  53. Am I done yet?


Those are today's thoughts.

Sunday, September 13, 2009

Practical Unix/Linux GNU Find Command Examples

Find is a very popular program for searching for a particular set of files. If you combine the find command with other applications like 'grep' or any other command then you will be even more productive. Here are some practical examples in the listings below. The commands are run Mac OSX, Darwin Kernel Version 9.8.0.

Find Man Page (bsd unix)

AME
find -- walk a file hierarchy

SYNOPSIS
find [-H | -L | -P] [-EXdsx] [-f pathname] pathname ... expression
find [-H | -L | -P] [-EXdsx] -f pathname [pathname ...] expression

DESCRIPTION
The find utility recursively descends the directory tree for each pathname
listed, evaluating an expression (composed of the ``primaries'' and
``operands'' listed below) in terms of each file in the tree.
...
...

Basic Find

Here the most basic usage for find.



After running the command, a listing of the files with the extension .m (objc code) are displayed.

Basic Find, other extensions

Here is an example of find with .m files and .h files.



227:octanemech berlinbrown$ find . \( -name '*.m' -or -name '*.h' \)
./Classes/EAGLView.h
./Classes/EAGLView.m

Find and executing commands on each file
The find command is not as powerful by itself. You can execute commands on each file that will be returned by the find command. Here is a useful example, find a set of files and perform grep on each file.

27:octanemech berlinbrown$ find . -name '*.m' -exec grep -H Berlin {} \;
./Classes/EAGLView.m:// Created by Berlin Brown on 9/2/09.
./Classes/octanemechAppDelegate.m:// Created by Berlin Brown on 9/2/09.
./main.m:// Created by Berlin Brown on 9/2/09.
227:octanemech berlinbrown$


The {} argument expands to a set of filenames.

Here is another common one-liner, remove all of the subversion .svn system directories. This command will turn your directory back to the way it was before you used it for your subversion project.

find . -name '.svn' -exec rm -Rvf {} \;

Find, exec and wc (line/character count)
I am software developer and I am need to use the wc command to count the number of lines in a source file. Here is an example:

227:octanemech berlinbrown$ find . -name '*.m' -exec wc -l {} \;
276 ./Classes/EAGLView.m
542 ./Classes/octanemechAppDelegate.m
323 ./Classes/Texture2D.m
18 ./main.m

Or

227:octanemech berlinbrown$ wc `find . -name '*.m'`
276 826 8426 ./Classes/EAGLView.m
542 1830 17171 ./Classes/octanemechAppDelegate.m
323 1216 10513 ./Classes/Texture2D.m
18 48 364 ./main.m
1159 3920 36474 total
227:octanemech berlinbrown$ wc -l `find . -name '*.m'`
276 ./Classes/EAGLView.m
542 ./Classes/octanemechAppDelegate.m
323 ./Classes/Texture2D.m
18 ./main.m
1159 total

There is one issue with running find this way, you may not get the totals, I want to use awk in one of the find/wc examples:

227:octanemech berlinbrown$ find . \( -name '*.h' -or -name '*.m' \) -exec wc -l {} \; | awk '{s+=$1} END {print s}'
1385

In natural language, after running the command above, it might read as; Find all of the files with the extension .h or .m, execute the wc command on the files, pipe the output to awk and sum the total.
Adding more filters
Here is the one-liner to find files that or at least 5k.

find . -name '*.m' -size +10k

27:octanemech berlinbrown$ find . -name '*.m' -size +1k
./Classes/EAGLView.m
./Classes/octanemechAppDelegate.m
./Classes/Texture2D.m

To find the files that have been modified within the last day:

find . -mtime -1
or 60 minutes...
find . -mmin -60

More Find Examples

Find then do a search and replace with 'sed' (replace with empty string):

find -name '*.java' -exec sed -i 's/SOME_KEYWORD//g' {} \;

Find files with *.h,*.m extensions and copy to a directory:

find -name '*.h' -or -name '*.m' -exec cp -vf {} ./tmp \;

Count number of total lines for a set of files using awk:

find . -name '*.d' -exec awk '{print NR}' {} +

$ wc -l `find . -name '*.m'` | sort
...
370 ./Inputs/Gesture.m
378 ./Models/k_wing.m
422 ./TouchFighterAppDelegate.m
444 ./GameObjects/Bullets.m
473 ./Core/ParticleSystemObject.m
572 ./Support/OpenGL/Texture2D.m
837 ./GameObjects/SpaceShip.m
1343 ./TouchFighterView.m
12745 total

Thursday, September 3, 2009

iPhone Development on Win32 Redux (build error log)

I was trying to build the iPhone toolchain according to "PJ Cabrera's - Write native iPhone applications using Eclipse CDT" article. I made it pretty far with some minor hiccups. I know there is a lot of noise in this blog entry, but I wanted to post the error in case it comes up again. As of yet, I still haven't gotten the win32/iphone/opengl examples to work. Plus, I have the issue of a simulator. The simulator doesn't exist for win32.

Yea, your best bet is to just get a Mac and do iPhone development on it.

You can view the current source here:

http://haskellnotebook.googlecode.com/svn/trunk/iphone/gl/HelloWorldWin32/

Error 2 (OpenGL)

OK, I was able to build an application, I had some issues with OpenGL apps.


/usr/local/bin/arm-apple-darwin9-gcc -c -I/usr/local/lib/gcc/arm-apple-darwin9/4.2.1/include -isysroot /usr/local/iphone-sysroot HelloWorld.m -o HelloWorld.o
In file included from HelloWorldApp.h:11,
from HelloWorld.m:11:
/usr/local/iphone-sysroot/usr/include/OpenGLES/EAGL.h:27: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'EAGLRenderingAPI'
/usr/local/iphone-sysroot/usr/include/OpenGLES/EAGL.h:59: error: expected ')' before 'EAGLRenderingAPI'
/usr/local/iphone-sysroot/usr/include/OpenGLES/EAGL.h:60: error: expected ')' before 'EAGLRenderingAPI'
/usr/local/iphone-sysroot/usr/include/OpenGLES/EAGL.h:65: error: expected specifier-qualifier-list before 'EAGLRenderingAPI'
make: *** [HelloWorld.o] Error 1



Error 1:

OK, to fix the one error there, I need to make sure that the symbolic links for some of the gcc libraries were correct.

Here is the script to correct this problem:

http://haskellnotebook.googlecode.com/svn/trunk/iphone/gl/HelloWorldWin32/ScriptTryFixLib_Links.sh

But, now I am stumped again, here is the trace of the Makefile output: Anyone have any ideas?

/usr/local/bin/arm-apple-darwin9-gcc -framework CoreFoundation -framework Foundation -framework UIKit -lobjc -bind_at_load -isysroot /usr/local/iphone-sysroot -o HelloWorld HelloWorld.o HelloWorldApp.o
/usr/local/bin/arm-apple-darwin9-ld: /usr/local/iphone-sysroot/usr/lib/libstdc++.6.dylib truncated or malformed object (mach header extends past the end of the file)
/usr/local/bin/arm-apple-darwin9-ld: warning multiple definitions of symbol _NSStreamDataWrittenToMemoryStreamKey
make: *** [HelloWorld] Error 1