Find a jar file given the class name? - java

This must be a very basic question for Java developers, but what is the best way to find the appropriate jar file given a class name?
For example, given "com.ibm.websphere.security.auth.WSSubject", how do you track down the appropriate jar file? ("google" is not the answer I'm looking for!)
The java docs do not give any hint of the jar file, and obviously the names of the jar files themselves offer no clue.
There must be a 'search local jars', or some sort of 'auto-resolve dependencies', trick in the java world. Ideally, I'm looking for the 'official' way to do this. I happen to be on a windows machine without cygwin.

Save this as findclass.sh (or whatever), put it on your path and make it executable:
#!/bin/sh
find "$1" -name "*.jar" -exec sh -c 'jar -tf {}|grep -H --label {} '$2'' \;
The first parameter is the directory to search recursively and the second parameter is a regular expression (typically just a simple class name) to search for.
$ findclass.sh . WSSubject
The script relies on the -t option to the jar command (which lists the contents) and greps each table of contents, labelling any matches with the path of the JAR file in which it was found.

There is no "official" Java way to do this AFAIK.
The way I usually hunt for it is to use find and jar to look through all jar files in a given tree.
> find . -name \*.jar -print -exec jar tf {} oracle/sql/BLOB.class \;
./v2.6.1/lib/csw_library.jar
./v2.6.1/lib/oracle_drivers_12_01.jar
oracle/sql/BLOB.class
If you're on Windows and don't want to install Cygwin, then I suppose you would have to write a batch script to locate the jar files.

I have written a program for this:
https://github.com/javalite/jar-explorer
It will also decompile existing byte code to show you interfaces, methods, super classes, will show contents of other resources - text, images, html, etc.

You could try services like:
http://www.jarhoo.com/
http://www.docjar.com/
http://javacio.us/
http://merobase.com/
Or
Google Desktop with the Airbear Software's IndexZip Plug-in
Or
A maven enterprise repository with a search feature e.g. Nexus (OFC, this would only work if the jars you're looking for are indexed i.e. installed in the repository)
PS: Jarhoo has teamed up with Javacio.us to provide 100,000 Java developers with free access to Jarhoo via links integrated with their Google search results. Subscription to Javacio.us is free and open to anyone with a Google account. For more information, please visit the Jarhoo offer page at Javacio.us.

If the grep on your system (e.g. Solaris) doesn't have -H and --label as used in Dan Dyer's example, you can use:
find . -name '*.jar' -type f | xargs -i bash -c "jar -tvf {}| tr / . | grep WSSubject && echo {}"

To search all jars under the current directory and return the one(s) that contain class a.b.c.D do a:
find . -iname *.jar | while read JARF; do jar tvf $JARF | grep a/b/c/D.class && echo $JARF ; done
It will report all instances of class a.b.c.D (or classes with a similar suffix) and will only print the jars that contain it.
Typical output:
$ find . -iname *.jar | while read JARF; do jar tvf $JARF | grep Log.class && echo $JARF ; done
479 Fri Oct 10 18:19:40 PDT 2003 org/apache/commons/logging/Log.class
3714 Fri Oct 10 18:19:40 PDT 2003 org/apache/commons/logging/impl/Log4JCategoryLog.class
1963 Fri Oct 10 18:19:40 PDT 2003 org/apache/commons/logging/impl/NoOpLog.class
9065 Fri Oct 10 18:19:40 PDT 2003 org/apache/commons/logging/impl/SimpleLog.class
./WebContent/WEB-INF/lib/commons-logging.jar

In Windows, run cmd.exe and type:
for %i in (*.jar) do #jar tvf %i | find "/com/company/MyClass.class"
The jars would have to be in the current directory. For also has a /R option which takes a directory and lets you search recursively.
If Jar.exe isn't in your path, you can do something like #C:\jdk\bin\jar.exe.

Try findjar.com. If it's in the public domain, you should get it. There's alos mavenjava.com (but that site seems to be down)

Printing the list as I go so I can see what I'm checking. Mostly I'm looking in a lib/app directory, but you can substitute a locate for the find.
e.g.
for jar in $(find some_dir/lib -name "*.jar" );
do
echo -------------$jar-------------------
jar -tf $jar | grep TheNameOfTheClassImLookingFor
done

Given your comment on attempting to handle dependencies, what I would do is focus on which libraries you are using. Knowing this, you will know what jars have to be on the classpath, and you can pay attention to that. There are also dependency management builders (Maven and Ant being two popular ones) that can package up projects with their dependencies inside. However, in the end, it is up to the developer to know which dependencies they have, and to pay attention to the requirements for those dependencies. This is one reason why using an IDE like Eclipse, and build tools like Maven or Ant are so nice in large projects, as when you have 20 dependencies for a project, that can become pretty unmanageable.

I use jarscan. It is an executable jar file that can recursively search an entire folder structure for jars that contain the class that you are looking for. It searches by class name, package name or regex.

In windows powershell you can use this command. It list all the JAR files it encounters, but it has an extra line that's very easy to spot where it also finds your class.
Get-ChildItem -recurse -Filter *.jar | Foreach {echo $_.fullname; c:\somepath\JDK\BIN\jar tvf $_.fullname | Select-String -pattern "Cabbages.class"}

There is also this web site that seems to be usefull.
http://www.findjar.com/

locate .jar | xargs grep com.ibm.websphere.security.auth.WSSubject

if you are still searching for WSSubject, then jar is wssec.jar. WSSecurityException class inside sas.jar

I recommend using Maven, Eclipse and m2eclipse.
Step 1 - add specific import
Step 2 - find and download (automatically) desired jar

Building up on Dan's excellent answer, the following script solves the problem of mangled output in case some of the jars are actually broken symlinks (while at the same time not skipping proper symlinks) It also searches in the current directory if no argument is provided.
#!/usr/bin/env bash
if [[ ($# -ne 1) && ($# -ne 2) ]]
then
echo "usage is $0 <grep RegEx to look for in contents of jar> [<top-of-folder-hierarchy> or, if missing, current dir]"
else
REG_EXP=$1
DIR=${2:-.}
if [ ! -d $DIR ]; then
echo "directory [$DIR] does not exist";
exit 1;
fi
find "$DIR" -name "*.jar" -exec sh -c '
(test -e {})
exitStatus=$?
if [ "$exitStatus" -eq 0 ]; then # this is done to avoid broken symlinks
jar -tf {}|grep -i -H --label {} '$REG_EXP'
fi
' \;
fi

in Intellij Idea
on your class press ctrl+B and after that you can find the jar file.
on project bar press scroll from source.
you can see the jar file contains the class.

Related

Get help/examples/documentation from jdk folder

I have Java practical exam in few days.
We have to write programs on notepad, and execute them through cmd (using jdk).
So my question is, is there any way that I can access help/documentation in JDK folder? All I want is syntax and method names, etc.
This is because in last exam, I lost all my marks because I wrote
public class abc extends applet
instead of
public class abc extends Applet
The compilation error wasn't helping. If I had access to the syntax, this wouldn't have happened.
Check whether the JDK contains the file src.zip. Since this is on option that can be turned off during installation, it’s not possible to predict whether it will be there, but it’s on by default.
If the file is there, you can use it to generate almost the same documentation you find here.
First extract the files. In theory, javadoc could read them directly from the zip file, in practice, it doesn’t work.
On windows, use
mkdir classes
cd classes
path-to-jdk\bin\jar xf path-to-jdk\src.zip
cd ..
Second, generate the documentation
mkdir doc
path-to-jdk\bin\javadoc -d doc -sourcepath classes -classpath path-to-jdk\jre\lib\rt.jar -subpackages java:javax
Afterwards, the file doc\index.html contains the starting point of the API documentation, equivalent to the one linked above.
It’s a challenge to read them if you don’t have a browser, but actually, it’s always present, i.e. if you click on the “Show Help” menu item in Notepad, it’ll open a browser. If that’s a too obvious rule bending, you can use the “Open File” dialog instead. Just enable “All Files” and the preview window, and it will show the contents of HTML files if you select them, while technically being still in a file dialog of Notepad rather than a browser…
Using javac command to see the compiling error.
If JAVA_HOME environment not set, you can use commands to find the jdk path:
//On Linux
echo $PATH
//On Windows
echo %PATH%
If you forget the class in which package, you can use jar command to find the class:
//On Linux
jar -tf $JAVA_HOME/jre/lib/rt.jar | grep -i "applet\.class$"
//On Windows
jar -tf %JAVA_HOME%/jre/lib/rt.jar | findstr -i -r "applet\.class$"
If you don't know method in Applet, you can use javap command to dump all visible methods,for example: I want a resize method.
//On Linux
javap -p java.applet.Applet | grep resize
//On Windows
javap -p java.applet.Applet | findstr resize
OR if you want override some method, you also can use javap command to dump all protected methods:
//On Linux
javap -protected java.awt.Component | grep protected
//On Windows
javap -protected java.awt.Component | findstr protected

How to use sed command to change java package declaration in batch way

Previously, my java package declarations all start with 'zn' like "package zn.tree". Now after I changed the java folder path to remove 'zn' folder, I also want to change all java declarations to remove the prefix 'zn.' in a batch way. For example, I want change "package zn.tree" to "package tree".
So I decided to use bash script to change all the java files. After I googled, I wrote a script to use 'sed' command to do this job. However, it doesn't work and reports error. I still don't get familiar with the regex in 'sed'. My code is shown below:
#! /bin/bash
# change package declaration in batch way
for path in $(find $1 -type f -name "*.java"); do
sed -i "" 's/\<zn/.\>//g' $path
done
Hope someone could give me some clues. Thank you.
If I understand your question, you could do it with a one liner like,
find . -type f -name '*.java' -exec sed -i 's/^package zn\./package /1' {} \;
That will execute the sed command and instruct it to edit in-place on every matching file. Note that I assume you want to match the first line starting with "package zn." and replace it with "package " once.
Using the refactoring feature of an IDE such as Eclipse, IntelliJ or Netbeans will save you a lot of time for those needs. In IntelliJ, you would just create your new package and drag-and-drop your classes from the old package to the new one.

Search for a String inside all files inside a war

Where I work someone had Java project and used Eclipse to export that project into a .war package.
Now I need to search for a string inside all the files that make that .war package. I know that a .war package is just a .zip file, and I have extracted its contents, however, now I have bunch of of .class java files (among images, xmls and other stuff) and I have no idea on how to search strings inside them.
I am a Linux Mint user, so I tried using the "grep -R stringHere ." command without success (I am not an advanced user), this command only searches inside text files.
I also searched and found the crgrep project but it is currently bugged and it does not work.
Does anyone know a linux command that can search inside all the contents of a .war package and check if those contents contain a specific string or code sample?
I really need to find a way to search through the content of the .class files. That is my only priority so far. I don't care about images nor about any other type of text files.
It would help a lot.
Thanks in advance, Pedro.
Unzip your war like any regular zip and from the root search with
find . -name "*.class" -print0 |xargs -0 strings -f |grep -i <your string>
Pray that your string got encoded in clear text inside the binaries.
This is quite simple, you can use something like below.
find /path -name "*.*" -exec grep -l "string-to-search"{} \;
If you need to search by ignoring case, you can use the -i along -l.
You can read further here.
I would recommend you to use jad.
Once installed, the following command should work just fine:
find . -name "*.class" | xargs jad -p | grep "your string"
Using find command:
find mywar.war -name '*.class' -exec strings -f "{}" + | grep "mysearchstringhere"
It is not a java question.
You can however use strings command:
find . -name "*.class" | xargs strings | grep myString
It will probably find string that you are looking for. But why are you looking for string in compiled binary file? What kind of string are you expecting to locate? If this is your code why not to search for strings in the source code, i.e. java files?
The .war file do not have the source code within them. You will see compiled .class files. This can't be read or you won't find anything meaningful in them.
From your question, I think you will have to use a decompiler to convert the .class to .java files. I would suggest the following options.
Cavaj, (no support for WIN 7 + ) .. here..
jad, (my personal favourite).. here
The advantage with jad is that it comes with a neat eclipse plug in .. download it here
So once you have decompiled the .class files, you can use any tools ( like grep ) to search for the string..

How to get names of classes inside a jar file?

I have a JAR file and I need to get the name of all classes inside this JAR file. How can I do that?
I googled it and saw something about JarFile or Java ClassLoader but I have no idea how to do it.
You can use Java jar tool. List the content of jar file in a txt file and you can see all the classes in the jar.
jar tvf jarfile.jar
-t list table of contents for archive
-v generate verbose output on standard output
-f specify archive file name
Unfortunately, Java doesn't provide an easy way to list classes in the "native" JRE. That leaves you with a couple of options: (a) for any given JAR file, you can list the entries inside that JAR file, find the .class files, and then determine which Java class each .class file represents; or (b) you can use a library that does this for you.
Option (a): Scanning JAR files manually
In this option, we'll fill classNames with the list of all Java classes contained inside a jar file at /path/to/jar/file.jar.
List<String> classNames = new ArrayList<String>();
ZipInputStream zip = new ZipInputStream(new FileInputStream("/path/to/jar/file.jar"));
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
// This ZipEntry represents a class. Now, what class does it represent?
String className = entry.getName().replace('/', '.'); // including ".class"
classNames.add(className.substring(0, className.length() - ".class".length()));
}
}
Option (b): Using specialized reflections libraries
Guava
Guava has had ClassPath since at least 14.0, which I have used and liked. One nice thing about ClassPath is that it doesn't load the classes it finds, which is important when you're scanning for a large number of classes.
ClassPath cp=ClassPath.from(Thread.currentThread().getContextClassLoader());
for(ClassPath.ClassInfo info : cp.getTopLevelClassesRecurusive("my.package.name")) {
// Do stuff with classes here...
}
Reflections
I haven't personally used the Reflections library, but it seems well-liked. Some great examples are provided on the website like this quick way to load all the classes in a package provided by any JAR file, which may also be useful for your application.
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);
Maybe you are looking for jar command to get the list of classes in terminal,
$ jar tf ~/.m2/repository/org/apache/spark/spark-assembly/1.2.0-SNAPSHOT/spark-assembly-1.2.0-SNAPSHOT-hadoop1.0.4.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/spark/
org/apache/spark/unused/
org/apache/spark/unused/UnusedStubClass.class
META-INF/maven/
META-INF/maven/org.spark-project.spark/
META-INF/maven/org.spark-project.spark/unused/
META-INF/maven/org.spark-project.spark/unused/pom.xml
META-INF/maven/org.spark-project.spark/unused/pom.properties
META-INF/NOTICE
where,
-t list table of contents for archive
-f specify archive file name
Or, just grep above result to see .classes only
$ jar tf ~/.m2/repository/org/apache/spark/spark-assembly/1.2.0-SNAPSHOT/spark-assembly-1.2.0-SNAPSHOT-hadoop1.0.4.jar | grep .class
org/apache/spark/unused/UnusedStubClass.class
To see number of classes,
jar tvf launcher/target/usergrid-launcher-1.0-SNAPSHOT.jar | grep .class | wc -l
61079
This is a hack I'm using:
You can use java's autocomplete like this:
java -cp path_to.jar <Tab>
This will give you a list of classes available to pass as the starting class. Of course, trying to use one that has no main file will not do anything, but you can see what java thinks the classes inside the .jar are called.
You can try:
jar tvf jarfile.jar
This will be helpful only if your jar is executable i.e. in manifest you have defined some class as main class
You can use the
jar tf example.jar
Below command will list the content of a jar file.
command :- unzip -l jarfilename.jar.
sample o/p :-
Archive: hello-world.jar
Length Date Time Name
--------- ---------- ----- ----
43161 10-18-2017 15:44 hello-world/com/ami/so/search/So.class
20531 10-18-2017 15:44 hello-world/com/ami/so/util/SoUtil.class
--------- -------
63692 2 files
According to manual of unzip
-l list archive files (short format). The names, uncompressed file sizes and modification dates and times of the specified files are
printed, along with totals for all
files specified. If UnZip was compiled with OS2_EAS defined, the -l option also lists columns for the sizes of stored OS/2
extended attributes (EAs) and OS/2 access
control lists (ACLs). In addition, the zipfile comment and individual file comments (if any) are displayed. If a file was
archived from a single-case file system
(for example, the old MS-DOS FAT file system) and the -L option was given, the filename is converted to lowercase and is
prefixed with a caret (^).
Mac OS:
On Terminal:
vim <your jar location>
after jar gets opened, press / and pass your class name and hit enter
You can try this :
unzip -v /your/jar.jar
This will be helpful only if your jar is executable i.e. in manifest you have defined some class as main class
Use this bash script:
#!/bin/bash
for VARIABLE in *.jar
do
jar -tf $VARIABLE |grep "\.class"|awk -v arch=$VARIABLE '{print arch ":" $4}'|sed 's/\//./g'|sed 's/\.\.//g'|sed 's/\.class//g'
done
this will list the classes inside jars in your directory in the form:
file1.jar:fullyqualifiedclassName
file1.jar:fullyqualifiedclassName
file1.jar:fullyqualifiedclassName
file1.jar:fullyqualifiedclassName
file2.jar:fullyqualifiedclassName
file2.jar:fullyqualifiedclassName
file2.jar:fullyqualifiedclassName
Sample output:
commons-io.jar:org.apache.commons.io.ByteOrderMark
commons-io.jar:org.apache.commons.io.Charsets
commons-io.jar:org.apache.commons.io.comparator.AbstractFileComparator
commons-io.jar:org.apache.commons.io.comparator.CompositeFileComparator
commons-io.jar:org.apache.commons.io.comparator.DefaultFileComparator
commons-io.jar:org.apache.commons.io.comparator.DirectoryFileComparator
commons-io.jar:org.apache.commons.io.comparator.ExtensionFileComparator
commons-io.jar:org.apache.commons.io.comparator.LastModifiedFileComparator
In windows you can use powershell:
Get-ChildItem -File -Filter *.jar |
ForEach-Object{
$filename = $_.Name
Write-Host $filename
$classes = jar -tf $_.Name |Select-String -Pattern '.class' -CaseSensitive -SimpleMatch
ForEach($line in $classes) {
write-host $filename":"(($line -replace "\.class", "") -replace "/", ".")
}
}
Description OF Solution : Eclipse IDE can be used for this by creating a sample java project and add all jars in the Project Build path
STEPS below:
Create a sample Eclipse Java project.
All all the jars you have in its Build Path
CTRL+SHIFT+T and Type the full class name .
Results will be displayed in the window with all the jars having that class. See attached picture .
windows cmd:
This would work if you have all te jars in the same directory and execute the below command
for /r %i in (*) do ( jar tvf %i | find /I "search_string")

Determine running classes and jar's from Linux ps output

My goal is to list to STDOUT the class files and .jar files being executed by java on a Linux server. I could do some getopts thing to get args to -jar, but other processes identified by
ps -ef | grep java or ps -eo args | grep java
might be executing a class file, e.g. java -classpath /a/b/c myclass A1 A2 . I am concerned that I am looking at an inelegant solution full of lengthy piplines of greps and awk's to solve what should be (I think) a straightforward query. Given that:
some calls are made to just 'java' and others to the fully qualified pathname for java,
a variety of different (or no) java options may be set on the command line for running a process,
some processes call .jar files, some call .class files, and
there may be args to the class,
what is the best way to get a simple list of running java executables, like:
abc.jar
mymainclass
xyz.jar
numainclass
I think that this may be a not uncommon question, but I can't seem to build a search string that locates any previous discussion here. An elegant solution would be nice; right now I am looking at grepping '-jar' entries to a getops call, and parsing the remainder considering all possible combinations. I am working on a solution in bash 3.x
Thanks!
The jps command introduced in jdk5 might be what you are looking for. Using the -l and -m options it will output the pid main class and arguments. Adding -v will add the vm arguments.
This option lists all Java files currently opened by a java command. Maybe it is useful to you.
lsof | grep -E "^java.*(.jar|.class)$" | sed -E "s/\s+/\t/g" | cut -f9
It works in Debian.

Categories