📄 serialversionuidadder.java
字号:
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2005 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.objectweb.asm.commons;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* A {@link ClassAdapter} that adds a serial version unique identifier to a
* class if missing. Here is typical usage of this class:
*
* <pre>
* ClassWriter cw = new ClassWriter(...);
* ClassVisitor sv = new SerialVersionUIDAdder(cw);
* ClassVisitor ca = new MyClassAdapter(sv);
* new ClassReader(orginalClass).accept(ca, false);
* </pre>
*
* The SVUID algorithm can be found <a href=
* "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
* >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
*
* <pre>
* The serialVersionUID is computed using the signature of a stream of bytes
* that reflect the class definition. The National Institute of Standards and
* Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
* signature for the stream. The first two 32-bit quantities are used to form a
* 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
* types to a sequence of bytes. The values input to the stream are defined by
* the Java Virtual Machine (VM) specification for classes.
*
* The sequence of items in the stream is as follows:
*
* 1. The class name written using UTF encoding.
* 2. The class modifiers written as a 32-bit integer.
* 3. The name of each interface sorted by name written using UTF encoding.
* 4. For each field of the class sorted by field name (except private static
* and private transient fields):
* 1. The name of the field in UTF encoding.
* 2. The modifiers of the field written as a 32-bit integer.
* 3. The descriptor of the field in UTF encoding
* 5. If a class initializer exists, write out the following:
* 1. The name of the method, <clinit>, in UTF encoding.
* 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
* written as a 32-bit integer.
* 3. The descriptor of the method, ()V, in UTF encoding.
* 6. For each non-private constructor sorted by method name and signature:
* 1. The name of the method, <init>, in UTF encoding.
* 2. The modifiers of the method written as a 32-bit integer.
* 3. The descriptor of the method in UTF encoding.
* 7. For each non-private method sorted by method name and signature:
* 1. The name of the method in UTF encoding.
* 2. The modifiers of the method written as a 32-bit integer.
* 3. The descriptor of the method in UTF encoding.
* 8. The SHA-1 algorithm is executed on the stream of bytes produced by
* DataOutputStream and produces five 32-bit values sha[0..4].
*
* 9. The hash value is assembled from the first and second 32-bit values of
* the SHA-1 message digest. If the result of the message digest, the five
* 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
* sha, the hash value would be computed as follows:
*
* long hash = ((sha[0] >>> 24) & 0xFF) |
* ((sha[0] >>> 16) & 0xFF) << 8 |
* ((sha[0] >>> 8) & 0xFF) << 16 |
* ((sha[0] >>> 0) & 0xFF) << 24 |
* ((sha[1] >>> 24) & 0xFF) << 32 |
* ((sha[1] >>> 16) & 0xFF) << 40 |
* ((sha[1] >>> 8) & 0xFF) << 48 |
* ((sha[1] >>> 0) & 0xFF) << 56;
* </pre>
*
* @author Rajendra Inamdar, Vishal Vishnoi
*/
public class SerialVersionUIDAdder extends ClassAdapter {
/**
* Flag that indicates if we need to compute SVUID.
*/
protected boolean computeSVUID;
/**
* Set to true if the class already has SVUID.
*/
protected boolean hasSVUID;
/**
* Classes access flags.
*/
protected int access;
/**
* Internal name of the class
*/
protected String name;
/**
* Interfaces implemented by the class.
*/
protected String[] interfaces;
/**
* Collection of fields. (except private static and private transient
* fields)
*/
protected Collection svuidFields;
/**
* Set to true if the class has static initializer.
*/
protected boolean hasStaticInitializer;
/**
* Collection of non-private constructors.
*/
protected Collection svuidConstructors;
/**
* Collection of non-private methods.
*/
protected Collection svuidMethods;
/**
* Creates a new {@link SerialVersionUIDAdder}.
*
* @param cv a {@link ClassVisitor} to which this visitor will delegate
* calls.
*/
public SerialVersionUIDAdder(final ClassVisitor cv) {
super(cv);
svuidFields = new ArrayList();
svuidConstructors = new ArrayList();
svuidMethods = new ArrayList();
}
// ------------------------------------------------------------------------
// Overriden methods
// ------------------------------------------------------------------------
/*
* Visit class header and get class name, access , and intefraces
* informatoin (step 1,2, and 3) for SVUID computation.
*/
public void visit(
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces)
{
computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0;
if (computeSVUID) {
this.name = name;
this.access = access;
this.interfaces = interfaces;
}
super.visit(version, access, name, signature, superName, interfaces);
}
/*
* Visit the methods and get constructor and method information (step 5 and
* 7). Also determince if there is a class initializer (step 6).
*/
public MethodVisitor visitMethod(
final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions)
{
if (computeSVUID) {
if (name.equals("<clinit>")) {
hasStaticInitializer = true;
}
/*
* Remembers non private constructors and methods for SVUID
* computation For constructor and method modifiers, only the
* ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
* ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
* are used.
*/
int mods = access
& (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
| Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
| Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
| Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
// all non private methods
if ((access & Opcodes.ACC_PRIVATE) == 0) {
if (name.equals("<init>")) {
svuidConstructors.add(new Item(name, mods, desc));
} else if (!name.equals("<clinit>")) {
svuidMethods.add(new Item(name, mods, desc));
}
}
}
return cv.visitMethod(access, name, desc, signature, exceptions);
}
/*
* Gets class field information for step 4 of the alogrithm. Also determines
* if the class already has a SVUID.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -