2

I guess this is kind of a follow-on to question 1522329.

That question talked about getting a list of all classes used at runtime via the java -verbose:class option.

What I'm interested in is automating the build of a JAR file which contains my class(es), and all other classes they rely on. Typically, this would be where I am using code from some third party open source product's "client logic" but they haven't provided a clean set of client API objects. Their complete set of code goes server-side, but I only need the necessary client bits.

This would seem a common issue but I haven't seen anything (e.g. in Eclipse) which helps with this. Am I missing something?

Of course I can still do it manually by: biting the bullet and including all the third-party code in a massive JAR (offending my purist sensibilities) / source walkthrough / trial and error / -verbose:class type stuff (but the latter wouldn't work where, say, my code runs as part of a J2EE servlet, and thus I only want to see this for a given Tomcat webapp and, ideally, only for classes related to my classes therein).

Community
  • 1
  • 1
Stuart Rossiter
  • 2,432
  • 1
  • 17
  • 20
  • To clarify )(see my comment to aperkins' response), how to automate a build is not the issue per se. It's how to determine the exact set of third-party classes that my classes use, so that I can build a "minimal" JAR library for them (and automate *this*). Of course, one response might be: "Stop worrying about this! If the third party developer hasn't cleanly separated out API classes, then just include the lot and accept the bloat.". I'm just interested if there's a clean alternative. – Stuart Rossiter Oct 07 '09 at 09:07
  • See also my answers to Vladimir's response for further clarification. An example use case is in the question: I have a library which is server-side code, but has a set of classes one can use client-side (or as general utilities for code which isn't part of the server). I want to extract just those classes (and all their dependencies) into a 'cleaner' JAR. I repeat that in some ways this is of academic/aesthetic interest since it's never really **practically** necessary. (Well, perhaps in an embedded context with very tight storage requirements.) – Stuart Rossiter Sep 25 '12 at 09:53

3 Answers3

5

I would recommend using a build system such as Ant or Maven. Maven is designed with Java in mind, and is what I use pretty much exclusively. You can even have Maven assemble (using the assembly plugin) all of the dependent classes into one large jar file, so you don't have to worry about dependencies.

http://maven.apache.org/

Edit:

Regarding the servlet, you can also define which dependencies you want packaged up with your jar, and if you are making a stand alone application you can have the jar tool make an executable jar.

note: yes, I am a bit of a Maven advocate, as it has made the project I work on much easier. No I do not work on the project personally. :)

aperkins
  • 12,914
  • 4
  • 29
  • 34
  • I've used Maven for years after switching from Ant. Best tool out there so far in my opinion. – SingleShot Oct 06 '09 at 15:57
  • That's good advice (I already use Ant, but get frustrated with the wordy XML syntax and might consider something like Maven), but doesn't really answer my question. Ant/Maven allows me to automate the build process, but what I'm asking is how I determine the *exact* set of classes that my classes use, so I can build a "minimal" relevant JAR file. AFAIK, there's no way of doing this with an Ant task. Of course, one response might be: "Stop worrying about this! If the third party developer hasn't cleanly separated out API classes, then just include the lot and accept the bloat.". – Stuart Rossiter Oct 07 '09 at 09:03
  • Do you have a _reason_ to worry about this? You're already using Java, worrying about class bloat is kinda silly. – Nick Veys Oct 07 '09 at 22:07
  • There is nothing specifically that will tell you what jar files you are dependent on - that is something the developer has to determine. Maven and Ant can help you manage this behavior in a reasonable way. – aperkins Oct 07 '09 at 23:25
2

Take a look at ProGuard.

ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier. It detects and removes unused classes, fields, methods, and attributes. It optimizes bytecode and removes unused instructions. It renames the remaining classes, fields, and methods using short meaningless names. Finally, it preverifies the processed code for Java 6 or for Java Micro Edition.

Juha Syrjälä
  • 33,425
  • 31
  • 131
  • 183
  • This looks like it could work but surely there are some more 'mainstream' solutions? Don't have time to investigate further and definitively accept this as an answer. Sorry :-( – Stuart Rossiter Sep 25 '12 at 09:50
1

What you want is not only to include the classes you rely on but also the classes, the classes you rely on, rely on. And so on, and so forth.

So that's not really a build problem, but more a dependency one. To answer your question, you can either solve this with Maven (apparently) or Ant + Ivy.

I work with Ivy and I sometimes build "ueber-jar" using the zipgroupfileset functionality of the Ant Jar task. Not very elegant would say some, but it's done in 10 seconds :-)

Vladimir
  • 6,853
  • 2
  • 26
  • 25
  • Only 3 years late in replying :-) I'll +1 this answer but, from what I can see of Ivy, this doesn't solve my problem as such. Ivy still requires metadata to state the dependencies, and the dependencies are still at a library/JAR level. What I wanted was, **for classes inside an existing JAR**, to be able to create a new JAR from a defined set of individual classes and then all their **internal** dependencies (**external** dependencies can remain as full JARs: it **would** be a little silly/anal to only extract the classes called (and their dependencies) in them). – Stuart Rossiter Sep 25 '12 at 09:49