聊一聊fastjson

2023-11-14


前言:fastjson是alibaba推出的java对象与JSON相互转化的java library,它以"快"著称 ,但是与Gson及jackson相比却有许多令人诟病的部分,那么我们就带着以下两个问题去了解fastjson
问题1:fastjson为什么快?
问题2:fastjson有哪些令人诟病的问题?

一.新手引导

1.什么是fastjson?

fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。

2.fastjson的优点

2.1 速度快

fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。

2.2 使用广泛

fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。

2.3 测试完备

fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。

2.4 使用简单

fastjson的API十分简洁。

String text = JSON.toJSONString(obj); //序列化
VO vo = JSON.parseObject("{...}", VO.class); //反序列化

2.5 功能完备

支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。

三.源码分析

3.1JSON.toJSONString

 //(1)将对象转化成json
        FastJsonExample example = new FastJsonExample();
        example.setId(1);
        example.setNick_name("男神");
        example.setRealName("石叶");
        String jsonExample = JSON.toJSONString(example);
        System.out.println("java object convert to json="+jsonExample);

3.1.1调用JSON.toJSONString(Object object)

public static String toJSONString(Object object) {
        return toJSONString(object, emptyFilters); //  emptyFilters = new SerializeFilter[0]
    }

 public static String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features) {
        return toJSONString(object, SerializeConfig.globalInstance, filters, null, DEFAULT_GENERATE_FEATURE, features);
    }
    其中 SerializeConfig.globalInstance = new SerializeConfig();

3.1.2初始化SerializeConfig

目的主要是去初始化serializers

public SerializeConfig() {
		this(IdentityHashMap.DEFAULT_SIZE); //默认大小8192
	}
 public SerializeConfig(int tableSize) {
        this(tableSize, false);
    }
    
public SerializeConfig(int tableSize, boolean fieldBase) {
		//默认false
	    this.fieldBased = fieldBase;
	    serializers = new IdentityHashMap<Type, ObjectSerializer>(tableSize);
        this.mixInSerializers = new IdentityHashMap<Type, IdentityHashMap<Type, ObjectSerializer>>(16);
		try {
		    if (asm) {
		        asmFactory = new ASMSerializerFactory();
		    }
		} catch (Throwable eror) {
		    asm = false;
		}
		//重点
        initSerializers();
	}

3.1.3initSerializers()

初始化serializers,将class类型 与对应的serializer做缓存,以1.2.62为例在com.alibaba.fastjson.serializer包下

private void initSerializers() {
        put(Boolean.class, BooleanCodec.instance);
        put(Character.class, CharacterCodec.instance);
        put(Byte.class, IntegerCodec.instance);
        put(Short.class, IntegerCodec.instance);
        put(Integer.class, IntegerCodec.instance);
        put(Long.class, LongCodec.instance);
        put(Float.class, FloatCodec.instance);
        put(Double.class, DoubleSerializer.instance);
        put(BigDecimal.class, BigDecimalCodec.instance);
        put(BigInteger.class, BigIntegerCodec.instance);
        put(String.class, StringCodec.instance);
        put(byte[].class, PrimitiveArraySerializer.instance);
        put(short[].class, PrimitiveArraySerializer.instance);
        put(int[].class, PrimitiveArraySerializer.instance);
        put(long[].class, PrimitiveArraySerializer.instance);
        put(float[].class, PrimitiveArraySerializer.instance);
        put(double[].class, PrimitiveArraySerializer.instance);
        put(boolean[].class, PrimitiveArraySerializer.instance);
        put(char[].class, PrimitiveArraySerializer.instance);
        put(Object[].class, ObjectArrayCodec.instance);
        put(Class.class, MiscCodec.instance);

        put(SimpleDateFormat.class, MiscCodec.instance);
        put(Currency.class, new MiscCodec());
        put(TimeZone.class, MiscCodec.instance);
        put(InetAddress.class, MiscCodec.instance);
        put(Inet4Address.class, MiscCodec.instance);
        put(Inet6Address.class, MiscCodec.instance);
        put(InetSocketAddress.class, MiscCodec.instance);
        put(File.class, MiscCodec.instance);
        put(Appendable.class, AppendableSerializer.instance);
        put(StringBuffer.class, AppendableSerializer.instance);
        put(StringBuilder.class, AppendableSerializer.instance);
        put(Charset.class, ToStringSerializer.instance);
        put(Pattern.class, ToStringSerializer.instance);
        put(Locale.class, ToStringSerializer.instance);
        put(URI.class, ToStringSerializer.instance);
        put(URL.class, ToStringSerializer.instance);
        put(UUID.class, ToStringSerializer.instance);

        // atomic
        put(AtomicBoolean.class, AtomicCodec.instance);
        put(AtomicInteger.class, AtomicCodec.instance);
        put(AtomicLong.class, AtomicCodec.instance);
        put(AtomicReference.class, ReferenceCodec.instance);
        put(AtomicIntegerArray.class, AtomicCodec.instance);
        put(AtomicLongArray.class, AtomicCodec.instance);

        put(WeakReference.class, ReferenceCodec.instance);
        put(SoftReference.class, ReferenceCodec.instance);

        put(LinkedList.class, CollectionCodec.instance);
    }
    
 public boolean put(Type type, ObjectSerializer value) {
        Type mixin = JSON.getMixInAnnotations(type);
        if (mixin != null) {
            IdentityHashMap<Type, ObjectSerializer> mixInClasses = this.mixInSerializers.get(type);
            if (mixInClasses == null) {
                //多线程下可能会重复创建,但不影响正确性
                mixInClasses = new IdentityHashMap<Type, ObjectSerializer>(4);
                mixInSerializers.put(type, mixInClasses);
            }
            return mixInClasses.put(mixin, value);
        }
        return this.serializers.put(type, value);
    }

3.1.4执行重载方法toJSONString

public static String toJSONString(Object object, // 
                                      SerializeConfig config, // 
                                      SerializeFilter[] filters, // 
                                      String dateFormat, //
                                      int defaultFeatures, // 
                                      SerializerFeature... features) {
         //初始化SerializeWriter                             
        SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);
        try {
        	//传入writer及config
            JSONSerializer serializer = new JSONSerializer(out, config);
            if (dateFormat != null && dateFormat.length() != 0) {
                serializer.setDateFormat(dateFormat);
                serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
            }
            if (filters != null) {
                for (SerializeFilter filter : filters) {
                    serializer.addFilter(filter);
                }
            }
            serializer.write(object);
            return out.toString();
        } finally {
            out.close();
        }
    }

3.1.5初始化SerializeWriter

继承Writer,真正的输出的关键
在这里插入图片描述

 public SerializeWriter(Writer writer, int defaultFeatures, SerializerFeature... features){
        this.writer = writer;
        buf = bufLocal.get();
        if (buf != null) {
            bufLocal.set(null);
        } else {
            buf = new char[2048];
        }
        int featuresValue = defaultFeatures;
        for (SerializerFeature feature : features) {
            featuresValue |= feature.getMask();
        }
        this.features = featuresValue;
        //使用&操作判断是否包含该features
        computeFeatures();
    }

3.1.6JSONSerializer.write(Object object)

 public final void write(Object object) {
 		//如果为null则写入"null"
        if (object == null) {
            out.writeNull();
            return;
        }
        //获取class
        Class<?> clazz = object.getClass();
        //获取class对应的serializer
        ObjectSerializer writer = getObjectWriter(clazz);
        try {
            writer.write(this, object, null, null, 0);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

3.1.7getObjectWriter获取class对应的serializer

public ObjectSerializer getObjectWriter(Class<?> clazz) {
        return config.getObjectWriter(clazz);
    }

public ObjectSerializer getObjectWriter(Class<?> clazz) {
        return getObjectWriter(clazz, true);
    }

private ObjectSerializer getObjectWriter(Class<?> clazz, boolean create) {
        ObjectSerializer writer = get(clazz);

        if (writer == null) {
            try {
                final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
                    if (!(o instanceof AutowiredObjectSerializer)) {
                        continue;
                    }

                    AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                    for (Type forType : autowired.getAutowiredFor()) {
                        put(forType, autowired);
                    }
                }
            } catch (ClassCastException ex) {
                // skip
            }

            writer = get(clazz);
        }

        if (writer == null) {
            final ClassLoader classLoader = JSON.class.getClassLoader();
            if (classLoader != Thread.currentThread().getContextClassLoader()) {
                try {
                    for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {

                        if (!(o instanceof AutowiredObjectSerializer)) {
                            continue;
                        }

                        AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                        for (Type forType : autowired.getAutowiredFor()) {
                            put(forType, autowired);
                        }
                    }
                } catch (ClassCastException ex) {
                    // skip
                }

                writer = get(clazz);
            }
        }

        for (Module module : modules) {
            writer = module.createSerializer(this, clazz);
            if (writer != null) {
                put(clazz, writer);
                return writer;
            }
        }
        
        if (writer == null) {
            String className = clazz.getName();
            Class<?> superClass;

            if (Map.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MapSerializer.instance);
            } else if (List.class.isAssignableFrom(clazz)) {
                put(clazz, writer = ListSerializer.instance);
            } else if (Collection.class.isAssignableFrom(clazz)) {
                put(clazz, writer = CollectionCodec.instance);
            } else if (Date.class.isAssignableFrom(clazz)) {
                put(clazz, writer = DateCodec.instance);
            } else if (JSONAware.class.isAssignableFrom(clazz)) {
                put(clazz, writer = JSONAwareSerializer.instance);
            } else if (JSONSerializable.class.isAssignableFrom(clazz)) {
                put(clazz, writer = JSONSerializableSerializer.instance);
            } else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MiscCodec.instance);
            } else if (clazz.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(clazz, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if ((superClass = clazz.getSuperclass()) != null && superClass.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(superClass, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if (clazz.isArray()) {
                Class<?> componentType = clazz.getComponentType();
                ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
                put(clazz, writer = new ArraySerializer(componentType, compObjectSerializer));
            } else if (Throwable.class.isAssignableFrom(clazz)) {
                SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy);
                beanInfo.features |= SerializerFeature.WriteClassName.mask;
                put(clazz, writer = new JavaBeanSerializer(beanInfo));
            } else if (TimeZone.class.isAssignableFrom(clazz) || Map.Entry.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MiscCodec.instance);
            } else if (Appendable.class.isAssignableFrom(clazz)) {
                put(clazz, writer = AppendableSerializer.instance);
            } else if (Charset.class.isAssignableFrom(clazz)) {
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Enumeration.class.isAssignableFrom(clazz)) {
                put(clazz, writer = EnumerationSerializer.instance);
            } else if (Calendar.class.isAssignableFrom(clazz) //
                    || XMLGregorianCalendar.class.isAssignableFrom(clazz)) {
                put(clazz, writer = CalendarCodec.instance);
            } else if (TypeUtils.isClob(clazz)) {
                put(clazz, writer = ClobSeriliazer.instance);
            } else if (TypeUtils.isPath(clazz)) {
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Iterator.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MiscCodec.instance);
            } else if (org.w3c.dom.Node.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MiscCodec.instance);
            } else {
                if (className.startsWith("java.awt.") //
                    && AwtCodec.support(clazz) //
                ) {
                    // awt
                    if (!awtError) {
                        try {
                            String[] names = new String[]{
                                    "java.awt.Color",
                                    "java.awt.Font",
                                    "java.awt.Point",
                                    "java.awt.Rectangle"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = AwtCodec.instance);
                                    return writer;
                                }
                            }
                        } catch (Throwable e) {
                            awtError = true;
                            // skip
                        }
                    }
                }
                
                // jdk8
                if ((!jdk8Error) //
                    && (className.startsWith("java.time.") //
                        || className.startsWith("java.util.Optional") //
                        || className.equals("java.util.concurrent.atomic.LongAdder")
                        || className.equals("java.util.concurrent.atomic.DoubleAdder")
                    )) {
                    try {
                        {
                            String[] names = new String[]{
                                    "java.time.LocalDateTime",
                                    "java.time.LocalDate",
                                    "java.time.LocalTime",
                                    "java.time.ZonedDateTime",
                                    "java.time.OffsetDateTime",
                                    "java.time.OffsetTime",
                                    "java.time.ZoneOffset",
                                    "java.time.ZoneRegion",
                                    "java.time.Period",
                                    "java.time.Duration",
                                    "java.time.Instant"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = Jdk8DateCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.Optional",
                                    "java.util.OptionalDouble",
                                    "java.util.OptionalInt",
                                    "java.util.OptionalLong"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = OptionalCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.concurrent.atomic.LongAdder",
                                    "java.util.concurrent.atomic.DoubleAdder"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = AdderSerializer.instance);
                                    return writer;
                                }
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        jdk8Error = true;
                    }
                }
                
                if ((!oracleJdbcError) //
                    && className.startsWith("oracle.sql.")) {
                    try {
                        String[] names = new String[] {
                                "oracle.sql.DATE",
                                "oracle.sql.TIMESTAMP"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = DateCodec.instance);
                                return writer;
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        oracleJdbcError = true;
                    }
                }
                
                if ((!springfoxError) //
                    && className.equals("springfox.documentation.spring.web.json.Json")) {
                    try {
                        put(Class.forName("springfox.documentation.spring.web.json.Json"), //
                                writer = SwaggerJsonSerializer.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        springfoxError = true;
                    }
                }

                if ((!guavaError) //
                        && className.startsWith("com.google.common.collect.")) {
                    try {
                        String[] names = new String[] {
                                "com.google.common.collect.HashMultimap",
                                "com.google.common.collect.LinkedListMultimap",
                                "com.google.common.collect.LinkedHashMultimap",
                                "com.google.common.collect.ArrayListMultimap",
                                "com.google.common.collect.TreeMultimap"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = GuavaCodec.instance);
                                return writer;
                            }
                        }
                    } catch (ClassNotFoundException e) {
                        // skip
                        guavaError = true;
                    }
                }

                if ((!jsonnullError) && className.equals("net.sf.json.JSONNull")) {
                    try {
                        put(Class.forName("net.sf.json.JSONNull"), writer = MiscCodec.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        jsonnullError = true;
                    }
                }
                
				if (!jsonobjectError && className.equals("org.json.JSONObject")) {
					try {
						put(Class.forName("org.json.JSONObject"), writer = JSONObjectCodec.instance);
						return writer;
					} catch (ClassNotFoundException e) {
						// skip
						jsonobjectError = true;
					}
				}

                if ((!jodaError) && className.startsWith("org.joda.")) {
                    try {
                        String[] names = new String[] {
                                "org.joda.time.LocalDate",
                                "org.joda.time.LocalDateTime",
                                "org.joda.time.LocalTime",
                                "org.joda.time.Instant",
                                "org.joda.time.DateTime",
                                "org.joda.time.Period",
                                "org.joda.time.Duration",
                                "org.joda.time.DateTimeZone",
                                "org.joda.time.UTCDateTimeZone",
                                "org.joda.time.tz.CachedDateTimeZone",
                                "org.joda.time.tz.FixedDateTimeZone",
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = JodaCodec.instance);
                                return writer;
                            }
                        }
                    } catch (ClassNotFoundException e) {
                        // skip
                        jodaError = true;
                    }
                }

                if ("java.nio.HeapByteBuffer".equals(className)) {
                    put(clazz, writer = ByteBufferCodec.instance);
                    return writer;
                }

                if ("org.javamoney.moneta.Money".equals(className)) {
                    put(clazz, writer = MonetaCodec.instance);
                    return writer;
                }

                Class[] interfaces = clazz.getInterfaces();
                if (interfaces.length == 1 && interfaces[0].isAnnotation()) {
                    put(clazz, AnnotationSerializer.instance);
                    return AnnotationSerializer.instance;
                }

                if (TypeUtils.isProxy(clazz)) {
                    Class<?> superClazz = clazz.getSuperclass();

                    ObjectSerializer superWriter = getObjectWriter(superClazz);
                    put(clazz, superWriter);
                    return superWriter;
                }

                if (Proxy.isProxyClass(clazz)) {
                    Class handlerClass = null;

                    if (interfaces.length == 2) {
                        handlerClass = interfaces[1];
                    } else {
                        for (Class proxiedInterface : interfaces) {
                            if (proxiedInterface.getName().startsWith("org.springframework.aop.")) {
                                continue;
                            }
                            if (handlerClass != null) {
                                handlerClass = null; // multi-matched
                                break;
                            }
                            handlerClass = proxiedInterface;
                        }
                    }
                    if (handlerClass != null) {
                        ObjectSerializer superWriter = getObjectWriter(handlerClass);
                        put(clazz, superWriter);
                        return superWriter;
                    }
                }
                //以上都不符合 创建serializer
                if (create) {
                    writer = createJavaBeanSerializer(clazz);
                    put(clazz, writer);
                }
            }
            if (writer == null) {
                writer = get(clazz);
            }
        }
        return writer;
    }

3.1.8createJavaBeanSerializer创建serializer

public final ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
		//获取class名称
        String className = clazz.getName();
        //转换成hashcode
        long hashCode64 = TypeUtils.fnv1a_64(className);
	    if (Arrays.binarySearch(denyClasses, hashCode64) >= 0) {
	        throw new JSONException("not support class : " + className);
        }
		//将对象信息转化成SerializeBeanInfo
	    SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
	    if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
	        return MiscCodec.instance;
	    }
		//创建真正的JavaBeanSerializer
	    return createJavaBeanSerializer(beanInfo);
	}

3.1.9初始化JavaBeanSerializer

在这里插入图片描述

 public JavaBeanSerializer(SerializeBeanInfo beanInfo) {
        this.beanInfo = beanInfo;
        //字段的Serializer
        sortedGetters = new FieldSerializer[beanInfo.sortedFields.length];
        for (int i = 0; i < sortedGetters.length; ++i) {
            sortedGetters[i] = new FieldSerializer(beanInfo.beanType, beanInfo.sortedFields[i]);
        }
        
        if (beanInfo.fields == beanInfo.sortedFields) {
            getters = sortedGetters;
        } else {
            getters = new FieldSerializer[beanInfo.fields.length];
            boolean hashNotMatch = false;
            for (int i = 0; i < getters.length; ++i) {
                FieldSerializer fieldSerializer = getFieldSerializer(beanInfo.fields[i].name);
                if (fieldSerializer == null) {
                    hashNotMatch = true;
                    break;
                }
                getters[i] = fieldSerializer;
            }
            if (hashNotMatch) {
                System.arraycopy(sortedGetters, 0, getters, 0, sortedGetters.length);
            }
        }

        if (beanInfo.jsonType != null) {
            for (Class<? extends SerializeFilter> filterClass : beanInfo.jsonType.serialzeFilters()) {
                try {
                    SerializeFilter filter = filterClass.getConstructor().newInstance();
                    this.addFilter(filter);
                } catch (Exception e) {
                    // skip
                }
            }
        }

        if (beanInfo.jsonType != null) {
            for (Class<? extends SerializeFilter> filterClass : beanInfo.jsonType.serialzeFilters()) {
                try {
                    SerializeFilter filter = filterClass.getConstructor().newInstance();
                    this.addFilter(filter);
                } catch (Exception e) {
                    // skip
                }
            }
        }
    }

3.1.10调动JavaBeanSerializer.write方法

4.JSON.parseObject解析

四.问题思考

4.1快的原因

针对转化有许多优化如使用buffer缓冲,string.subline 针对asm spring的特殊优化等

4.2令人诟病的问题

问题1 1.2.14版本前对 “_” 等特殊符号开头的字段兼容不够
问题2 存在硬编码
问题3 存在漏洞
问题4 社区不完善,英文文档不完善

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

聊一聊fastjson 的相关文章

  • 斌哥的 Docker 进阶指南

    过去的一年中 关于 Docker 的话题从未断过 而如今 从尝试 Docker 到最终决定使用 Docker 的转化率依然在逐步升高 关于 Docker 的讨论更是有增无减 另一方面 大家的注意力也渐渐从 Docker 是什么 转移到 实践
  • 如何正确控制springboot中bean的加载顺序总结

    1 为什么需要控制加载顺序 springboot遵从约定大于配置的原则 极大程度的解决了配置繁琐的问题 在此基础上 又提供了spi机制 用spring factories可以完成一个小组件的自动装配功能 在一般业务场景 可能你不大关心一个b
  • 数据结构之链表(LinkedList详解)

    文章目录 一 什么是LinkedList 二 LinkedList的使用 三 LinkedList自实现 四 链表实现逆序打印的两种方式 递归和非递归 五 ArrayList和LinkedList有什么区别 一 什么是LinkedList
  • 联想涉密专用计算机密码,清除BIOS密码大全(适用于联想全系列笔记本)

    清除BIOS密码大全 适用于联想全系列笔记本 互联网 发布时间 2008 11 28 22 29 42 作者 佚名 我要评论 昭阳笔记本电脑密码清除方法清除密码的工具 并口环路制作电路图代表1与5 10脚相连 以下同 1 5 102 113

随机推荐

  • 【Selenium4自动化测试(3)】第一个自动化测试用例

    3 1 搭建一个被测系统 为了开展本次课程 我们先搭建一个被测系统 安装vue element admin系统 下载Node https nodejs org en download 按操作步骤一直下一步即可 执行查看版本号 node v
  • Python中f-string的使用

    Python 3 6引入了一个新的格式化字符串的方法 f string formatted string 它可以直接把变量写在字符串中 使得格式化的字符串看起来很直观 下面对f string进行简单介绍 f string的简单使用 name
  • 如何让div中的内容垂直居中

    虽然Div布局已经基本上取代了表格布局 但表格布局和Div布局仍然各有千秋 互有长处 比如表格布局中的垂直居中就是Div布局的一大弱项 不过好在千变万化的CSS可以灵活运用 可以制作出准垂直居中效果 勉强过关 要让div中的内容垂直居中 无
  • 分析模式

    1 找方向 方向是最重要的 如果一开始找错了方向 那么努力多久都是白费 最开始一定要确定有多少方向 然后选择一个最靠谱的 2 过程中反思方向 在过程中一定要经常反思 自己的方向是否正确 是否还有其他方向 尤其是在碰壁之后一定要好好反思 3
  • STL list源码——实现框架、具体实现的详细分段剖析(迭代器的处理、list的实现)、list基本函数总结

    list的底层采用的数据结构是环形的双向链表 相对于vector容器的连续线性空间 list插入或删除要付出的代价比vector小很多 对空间的运用有绝对的精准 一点也不浪费 但是list带有链表天生的弱点 就是不支持随机访问 从内置的迭代
  • 超详细的零基础nodejs树状图~初始化nodejs~模块

    前言 学习任何新知识 最重要的永远都是搭建属于自己的知识框架 随后学习的细碎知识点往框架里面填入 最后形成一棵属于自己的知识大树 本系列的博客专注更新总结好的思维导图 希望可以帮助大家快速理清知识结构 一 初识Node js 内置模块 二
  • Attribute "result" must be declared for element type "select".

    返回结果声明错误 原因 定义返回类型与实际不匹配 修改前
  • 贪心算法原理及其应用

    概述 贪心算法应该算是那种 只闻其声不见其人 的算法 我们可能在好多地方都会听到贪心算法这一概念 并且它的算法思想也比较简单就是说算法只保证局部最优 进而达到全局最优 但我们实际编程的过程中用的并不是很多 究其原因可能是贪心算法使用的条件比
  • 学习Kali的笔记

    2022 4 15 查看当前使用的Shell类型 usr bin zsh 可以看到我们使用是zsh类型的shell centos7 使用的是bash类型的shell zsh功能更强 而且zsh完全兼容bash的用法和命令 配置apt命令在线
  • yolov5代码解读-dataset

    前言 下两篇 yolov5代码解读 网络架构 yolov5代码解读 训练 代码已上传到github 数据集和权重文件已上传到百度网盘 链接在github里 如需下载请移步 https github com scc max yolov5 sc
  • 理解密码学中的双线性映射

    回顾 什么是群 一 定义 定义1 设G是定义了一个二元运算 的集合 如果这个运算满足下列性质 1 封闭性 如果a和b都属于G 则a b也属于G 2 结合律 对于G中的任意元素a b和c 都有 a b c a b c 成立 3 单位元 G中存
  • 【华为OD】

    华为OD试题注意事项 使用合适的编程语言 在华为OD机试中多数情况下使用C 或Java 按照题目要求进行编码 仔细阅读题目描述并理解要求 在编码前可以进行伪代码编写或画流程图有助于理解和排除逻辑错误 注意代码的规范性 注重代码的可读性和可维
  • linux启动和停止springboot项目的命令

    1 启动命令 nohup java jar dingding function 0 0 1 SNAPSHOT jar gt catalina out 2 gt 1 2 命令详解 nohup 不挂断地运行命令 退出帐户之后继续运行相应的进程
  • Accessors are only available when targeting ECMAScript 5 and higher 错误提示

    来到这里 说明聪明又勤快的你 一定是在学习JavaScript的超大集群Typescript 幸幸苦苦写完代码 运行结果如下 error TS1056 Accessors are only available when targeting
  • 码云实战(一)——idea实现将本地的项目推送到码云上

    文章目录 前言 一 创建本地仓库并关联 二 将项目提交本地仓库 三 关联远程仓库 3 1 创建空白的远程库 四 推送到远程仓库 五 验证是否推送成功 总结 前言 本系列文章主要记录日常使用中碰到的码云的相关问题 一 创建本地仓库并关联 用I
  • Pandas知识点-详解聚合函数agg

    Pandas知识点 详解聚合函数agg Pandas提供了多个聚合函数 聚合函数可以快速 简洁地将多个函数的执行结果聚合到一起 本文介绍的聚合函数为DataFrame aggregate 别名DataFrame agg aggregate
  • 计算机共享打印怎么设置密码,共享打印机需要密码的解决方法

    Q 共享打印机 客户机访问主机计算机提示输入账户和密码如何解决 A 造成是此问题的原因是主机电脑安全级别较高造成的 在主机电脑按照以下方法调整即可解决 1 Windows XP 点击 开始 控制面板 WINDOWS防火墙 列外 将 文件和打
  • Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect

    Session 0x0 for server null unexpected error closing socket connection and attempting reconnect 错误原因 zookeeper没有正常启动 为了避
  • Linux系统下PORT端口引脚导出GPIO对应的序号关系

    文章首发于同名微信公众号 DigCore 欢迎关注同名微信公众号 DigCore 及时获取最新技术博文 PORT端口中的引脚序号与GPIOx的对应关系 GPIOx P 32 N P PORTA 0 PORTB 1 PORTC 2 N PA0
  • 聊一聊fastjson

    文章目录 一 新手引导 1 什么是fastjson 2 fastjson的优点 2 1 速度快 2 2 使用广泛 2 3 测试完备 2 4 使用简单 2 5 功能完备 三 源码分析 3 1JSON toJSONString 3 1 1调用J