Baruch Sadogursky, recently joined JFrog as the Developers Advocate following years of working alongside JFrog’s founding team. Prior to joining JFrog, Baruch was an innovations expert with BMC Software Incubator team after 6 years with AlphaCSP as a senior Java consultant, architect and training division manager. Baruch is hacking around Java technologies and Continuous-Integration tools since 2001, including module development for open source projects like Gradle & Spring. Baruch is also active in community development around Artifactory, participating in the development of it’s plugin ecosystem and enriching it’s functionality with open-source user plugins. As JFrog’s Developers Advocate, Baruch contributes to the strong collaboration with leading open-source projects such as SpringSource, Grails and Gradle by providing them with the Artifactory Cloud platform, and fuels the Continuous-Integration ecosystem with open-source plugins for leading tools such as Jenkins, TeamCity & Bamboo. Baruch blogs at http://blogs.jfrog.org & blog.sadogursky.com and tweets as @jbaruch. Baruch is a DZone MVB and is not an employee of DZone and has posted 14 posts at DZone. You can read more from them at their website. View Full User Profile

On Using the Right Tool for the Job

05.31.2012
| 2722 views |
  • submit to reddit
Disclaimer: The code samples in the post below are for brain teasing only. Do not, I repeat, do not ever do such things for any other purpose!

A friend of mine is a big fan of puzzlers. Any puzzlers, including programming ones. Here’s his latest and greatest:

Write some code in the static initializer to make the assert pass:

public class Test {
 static {
//Write some code here
 }

public static void main(String[] args) {
 Integer a = 20;
 Integer b = 20;
 assert (a + b == 60);
 }
}

Don’t forget to enable assertions if you want to solve this one (-ea as VM parameter).

If you solved it, or don’t feel like puzzlers, read on for the solution and the punchline.

First, the solution: You need to know refection and two facts about Integers to solve this one:

  1. Integers have cache for all values in range -128 to 127.
  2. Integers use that cache during auto-boxing (as opposite to using Integer’s constructor, for example).

Well, you also need to know the exact implementation of the Integer class to figure out where the cache is and what’s the name, but rt.jar sources are here for the rescue. Guess what? the cache is a private variable inside a private inner class. Joy-joy.

Here’s the plan:

  1. Get Integer’s class object.
  2. Get the list of its inner classes.
  3. Find the right one (what a relief, it only has one. Or not – it is subject to change in future versions since we are digging in highly encapsulated stuff . Duh.)
  4. Get the cache field from it.
  5. It’s private, set it to accessible in order to get the value of the field.
  6. Change the value of “20″ to be “30″

Here’s the code of the static initializer:

 static {
try {
 Class<?>[] declaredClasses = Integer.class.getDeclaredClasses();
 Field cacheField = declaredClasses[0].getDeclaredField("cache");
 cacheField.setAccessible(true);
 ((Integer[]) cacheField.get(null))[20 + 128] = 30;
 } catch (Exception e) { e.printStackTrace(); }
 }

Personally, I hate it. It’s ugly, it messes with very low-level encapuslated stuff that one even doesn’t suppose to know, and it is fragile (e.g. it won’t work if Integer is created with constructor).

And fairly, we just got lucky. If Integers did not have the cache then we would not  have any way to change what “+” does!

So, why this simple trick is so difficult to impossible to implement? Simple – Java is not intended for those tricks. Java is static, and it is good! It means that you can rely on it. 20+20 will (almost always) be 40. That is Good.

If you want to do dynamic stuff, like changing the behavior of  a “+” operator, you’d better use the right tool for the job. E.g. – Groovy.

Here’s the Groovy version of the puzzler:

//Write some code here
Integer a = 20
Integer b = 20
assert 60 == a + b

Looks almost the same (without the main() mess, some ridiculous semicolons and the need to include -ea in VM parameters), but the difference in the way to achieve the desired is huge. Since Groovy is dynamic it is intended to do stuff like changing the behavior of the plus sign. Here’s the facts about Groovy that you need to know to solve this one:

  1. Groovy operates with wrappers, always.
  2. Groovy implements operators though methods. “+” is implemented in plus() method.
  3. Using Groovy’s MetaClasses you can easily replace method with any closure.

Here’s the plan:

  1. Get Integer’s MetaClass.
  2. Replace plus() method with implementation that returns 60.

That’s all. Really. Here’s the code:

Integer.metaClass.plus = {int i -> 60 }

Nuff said. Now you only have 2 options. Stop doing those ugly tricks, or at least do it with the right tools for the job.

 

 

 

 

 

 

 

 

Published at DZone with permission of Baruch Sadogursky, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Dapeng Liu replied on Fri, 2012/06/01 - 9:04am

the sample is so boring, and by all meanings it is out right wrong ... if you would want to demo the ability to override an operator ... there could be a million better samples than this ...

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.