Java中对象序列化机制的优化研究

Java中对象序列化机制的优化研究

对象序列化(Serialization)是Java编程中一种非常重要的机制,它允许将对象的状态转换为字节流,从而方便存储或网络传输。然而,Java的默认序列化机制虽然功能强大,但在性能、灵活性和兼容性等方面仍存在一定的不足。本篇文章将深入探讨Java对象序列化机制的优化研究,帮助开发者提高系统的效率与性能。

1. 什么是对象序列化?

对象序列化是指将对象的状态转化为字节流的过程,序列化后的对象可以存储到磁盘或通过网络进行传输。Java通过java.io.Serializable接口实现对象的序列化。

1.1 默认序列化

Java对象实现Serializable接口后,可以通过ObjectOutputStream类来将对象序列化,ObjectInputStream类来将字节流反序列化为对象。下面是一个简单的序列化和反序列化的示例:

import java.io.*;class Person implements Serializable {private static final long serialVersionUID = 1L;private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}public class SerializationExample {public static void main(String[] args) {try {// 序列化Person person = new Person("John", 30);ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"));out.writeObject(person);out.close();// 反序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"));Person deserializedPerson = (Person) in.readObject();in.close();System.out.println("反序列化后的对象:" + deserializedPerson);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

在上述代码中,我们定义了一个Person类并实现了Serializable接口,之后使用ObjectOutputStream将对象序列化到文件中,再用ObjectInputStream将其反序列化回对象。

2. 默认序列化机制的缺点

虽然Java的默认序列化机制非常简单,但它也存在一些问题,主要包括:

  • 性能问题:默认序列化需要遍历对象的所有字段,并进行逐个序列化,这样会带来不必要的开销,尤其是在对象很大时。
  • 兼容性问题:当类发生变更(如字段添加或删除)时,默认序列化可能会导致反序列化失败。
  • 缺乏灵活性:Java的默认序列化机制是自动的,没有提供对序列化过程的细粒度控制。

因此,为了提高序列化的性能和灵活性,许多开发者选择使用优化的序列化机制。

3. 对象序列化优化的常见方法

3.1 使用transient关键字

transient关键字可以标记那些不需要序列化的字段。这样可以避免不必要的字段序列化,从而提高性能。

例如,如果Person类有一个字段是临时计算的值(比如缓存的年龄),我们可以将其标记为transient,这样它就不会被序列化。

class Person implements Serializable {private static final long serialVersionUID = 1L;private String name;private transient int age; // 不序列化这个字段public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}

使用transient后,age字段在序列化时不会被写入,反序列化后它会被初始化为默认值(如0)。

3.2 自定义序列化方法

Java允许开发者通过实现readObjectwriteObject方法来自定义序列化和反序列化过程。这使得开发者可以完全控制哪些字段需要被序列化,以及如何序列化。

class Person implements Serializable {private static final long serialVersionUID = 1L;private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}private void writeObject(ObjectOutputStream out) throws IOException {out.defaultWriteObject();  // 写入默认的字段out.writeInt(age * 2);  // 将age字段做一些处理再序列化}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject();  // 读取默认的字段this.age = in.readInt() / 2;  // 对反序列化后的age字段进行处理}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}

在这个例子中,我们通过自定义writeObjectreadObject方法实现了对age字段的特殊处理。这样可以避免默认序列化行为的一些问题,并提供更高效的序列化。

3.3 使用Externalizable接口

Java提供了Externalizable接口,它比Serializable接口更加灵活,允许开发者完全控制序列化和反序列化的过程。与Serializable不同,Externalizable要求实现两个方法:writeExternal()readExternal()

import java.io.*;class Person implements Externalizable {private String name;private int age;public Person() {  // 必须有无参构造函数}public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic void writeExternal(ObjectOutput out) throws IOException {out.writeObject(name);out.writeInt(age);  // 自定义序列化过程}@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {name = (String) in.readObject();age = in.readInt();  // 自定义反序列化过程}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}

Externalizable的优势在于它提供了更高的灵活性和性能,因为它允许开发者明确控制序列化的细节。

3.4 使用第三方库(如Kryo)

除了Java自带的序列化机制,第三方库(如Kryo)提供了更高效的序列化方式。Kryo是一个高效的Java对象图序列化/反序列化库,速度比Java原生序列化机制要快得多,并且支持更加灵活的对象处理。

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.io.Input;public class KryoExample {public static void main(String[] args) {Kryo kryo = new Kryo();kryo.register(Person.class);Person person = new Person("John", 30);// 序列化Output output = new Output(1024);kryo.writeObject(output, person);output.close();// 反序列化Input input = new Input(1024);Person deserializedPerson = kryo.readObject(input, Person.class);input.close();System.out.println("反序列化后的对象:" + deserializedPerson);}
}

Kryo的序列化性能相比Java原生序列化机制有显著提升,尤其适用于需要频繁进行对象序列化的场景。

4. 对象序列化优化的进阶技术

在实际应用中,对于对象序列化的优化不仅限于基础方法,许多复杂的场景还需要更多的定制化和进阶技巧。以下是一些较为高级的优化方案,能够在极端场景下进一步提升性能与可靠性。

4.1 对象图的深度优化

在默认的序列化机制中,所有被引用的对象都会被递归序列化,这在对象图较为复杂时会导致严重的性能问题。一个常见的优化策略是使用浅拷贝,避免递归序列化那些不需要的嵌套对象。

例如,在序列化一个嵌套复杂的对象图时,可以通过在类中手动控制深拷贝和引用关系的方式,来避免不必要的递归序列化,减少不必要的计算和内存消耗。

import java.io.*;class Employee implements Serializable {private String name;private transient Department department;  // 临时字段,不序列化public Employee(String name, Department department) {this.name = name;this.department = department;}public Department getDepartment() {return department;}@Overridepublic String toString() {return "Employee{name='" + name + "', department=" + department + "}";}
}class Department implements Serializable {private String deptName;public Department(String deptName) {this.deptName = deptName;}@Overridepublic String toString() {return "Department{deptName='" + deptName + "'}";}
}public class OptimizedSerialization {public static void main(String[] args) {try {Department dept = new Department("IT");Employee emp = new Employee("John", dept);// 自定义序列化:浅拷贝,避免递归序列化department对象ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.ser"));out.writeObject(emp);out.close();// 反序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("employee.ser"));Employee deserializedEmp = (Employee) in.readObject();in.close();System.out.println("反序列化后的员工:" + deserializedEmp);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

通过对Department字段使用transient关键字并且手动管理引用,我们避免了在序列化时对Department对象进行递归序列化。

4.2 对序列化数据进行压缩

另一种优化方法是在序列化后对字节流进行压缩处理,尤其适用于对象较大且需要频繁传输的场景。Java标准库提供了java.util.zip包来实现压缩和解压缩功能。

import java.io.*;
import java.util.zip.GZIPOutputStream;
import java.util.zip.GZIPInputStream;public class CompressedSerialization {public static void main(String[] args) {try {Person person = new Person("John", 30);// 使用GZIP压缩序列化数据ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream("person.gz")));out.writeObject(person);out.close();// 解压并反序列化数据ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new FileInputStream("person.gz")));Person deserializedPerson = (Person) in.readObject();in.close();System.out.println("反序列化后的对象:" + deserializedPerson);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

在这个例子中,我们使用GZIPOutputStreamGZIPInputStream对序列化数据进行了压缩和解压。压缩不仅能减小存储空间,还能提高网络传输效率,特别是在对象较大时,效果尤为明显。

4.3 使用对象池减少序列化次数

在某些场景下,频繁地进行序列化和反序列化操作会导致性能瓶颈。如果系统中存在大量重复使用的对象,可以通过对象池(Object Pool)技术来减少重复的序列化操作。

对象池可以缓存一些已序列化的对象,当需要重复使用时直接取出缓存对象,避免了每次都进行序列化/反序列化的开销。

import java.io.*;
import java.util.concurrent.*;public class ObjectPoolSerialization {private static final int POOL_SIZE = 10;private static final BlockingQueue<Employee> objectPool = new LinkedBlockingQueue<>(POOL_SIZE);public static void main(String[] args) throws InterruptedException {// 预先填充对象池for (int i = 0; i < POOL_SIZE; i++) {Employee emp = new Employee("Employee" + i, new Department("Department" + i));objectPool.offer(emp);}// 模拟获取对象池中的对象Employee emp = objectPool.take();System.out.println("从池中获取的对象:" + emp);}
}

通过使用BlockingQueue等并发工具类,可以在高并发的场景下更高效地管理对象池,减少多次序列化的操作,提高系统的响应速度。

4.4 结合缓存优化序列化

对于一些频繁需要序列化和反序列化的对象,如果对象内容不会频繁变化,可以考虑结合缓存(如Redis)进行优化。通过在缓存中存储序列化结果,避免重复的序列化/反序列化操作。这样不仅能节省CPU和内存开销,还能加速数据访问。

import java.io.*;
import java.util.HashMap;
import java.util.Map;public class CachedSerialization {private static final Map<String, byte[]> cache = new HashMap<>();public static byte[] serializeWithCache(Object obj, String key) throws IOException {// 检查缓存是否存在if (cache.containsKey(key)) {return cache.get(key);}// 序列化对象ByteArrayOutputStream byteStream = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(byteStream);out.writeObject(obj);out.flush();byte[] data = byteStream.toByteArray();cache.put(key, data); // 将序列化结果缓存return data;}public static Object deserializeWithCache(byte[] data) throws IOException, ClassNotFoundException {ByteArrayInputStream byteStream = new ByteArrayInputStream(data);ObjectInputStream in = new ObjectInputStream(byteStream);return in.readObject();}public static void main(String[] args) throws IOException, ClassNotFoundException {Person person = new Person("John", 30);byte[] serializedPerson = serializeWithCache(person, "person");// 从缓存中反序列化Person deserializedPerson = (Person) deserializeWithCache(serializedPerson);System.out.println("从缓存中反序列化的对象:" + deserializedPerson);}
}

在这个例子中,我们实现了一个简单的缓存机制,当序列化对象时先检查缓存,只有在缓存中没有时才进行实际的序列化操作。这可以显著减少序列化的次数,提升系统的响应效率。

4.5 性能评估与监控

无论采用何种优化策略,都需要进行严格的性能评估。通过Java的JMH(Java Microbenchmarking Harness)等工具进行基准测试,帮助开发者识别性能瓶颈并验证优化策略的效果。

4.6 高并发下的序列化优化

在高并发环境下,频繁的序列化操作可能会导致竞争条件和锁的争用。可以通过异步序列化、批量序列化和线程池等技术进行优化。例如,异步序列化能够将序列化任务放入队列中,交给单独的线程处理,从而避免主线程被阻塞。

5. 高效序列化与反序列化的应用场景

在一些特定的应用场景下,选择合适的序列化方式不仅能提升性能,还能解决实际业务中遇到的问题。以下是几个常见的场景,针对这些场景可以采用不同的优化策略,来确保序列化与反序列化的高效运行。

5.1 分布式系统中的数据传输

在分布式系统中,数据需要频繁在不同的节点之间进行传输。为了确保数据的快速传输,序列化效率至关重要。在这种场景下,通常不推荐使用Java默认的序列化机制,因为它相对较慢且体积较大。

优化方法:使用高效的序列化框架

如Apache Avro、Protocol Buffers(Protobuf)、Thrift等,这些框架都提供了比Java原生序列化更高效的序列化机制。

  • Protobuf:是一种语言中立、平台中立的序列化协议。它比Java默认序列化更加紧凑,并且速度更快,广泛应用于分布式系统中。

示例:使用Protobuf进行序列化

import com.google.protobuf.InvalidProtocolBufferException;public class ProtobufExample {public static void main(String[] args) {try {// 创建一个Person对象PersonProtos.Person person = PersonProtos.Person.newBuilder().setName("John").setAge(30).build();// 序列化byte[] serializedPerson = person.toByteArray();System.out.println("序列化数据长度:" + serializedPerson.length);// 反序列化PersonProtos.Person deserializedPerson = PersonProtos.Person.parseFrom(serializedPerson);System.out.println("反序列化后的对象:" + deserializedPerson.getName() + ", " + deserializedPerson.getAge());} catch (InvalidProtocolBufferException e) {e.printStackTrace();}}
}

Protobuf的优势在于它生成的字节码较小,反序列化速度快,尤其在高并发、高吞吐的分布式系统中,Protobuf可以显著减少网络传输的延迟。

5.2 微服务架构中的消息传递

在微服务架构中,服务之间通常通过消息队列或事件总线进行异步通信。在这种模式下,系统的消息传递效率和序列化性能变得尤为重要。

优化方法:选择合适的消息中间件与序列化方式
  • Kafka:作为分布式消息队列系统,Kafka的消息传输量非常大,消息内容序列化的性能直接影响到系统的整体吞吐量。
  • 选择合适的序列化协议:例如,使用JSON、Protobuf、Avro等格式来序列化消息数据。JSON格式相对灵活且易于调试,但在数据量大时性能较差。而Protobuf和Avro在序列化时更加高效,特别适合高负载、高并发的环境。
// 示例:使用Avro序列化消息
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.generic.GenericData;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.DataFileWriter;import java.io.File;
import java.io.IOException;public class AvroExample {public static void main(String[] args) throws IOException {// 定义Avro schemaString schemaString = "{\"type\":\"record\",\"name\":\"Person\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"int\"}]}";Schema schema = new Schema.Parser().parse(schemaString);// 创建Avro记录GenericRecord person = new GenericData.Record(schema);person.put("name", "John");person.put("age", 30);// 序列化File file = new File("person.avro");DatumWriter<GenericRecord> datumWriter = new org.apache.avro.specific.SpecificDatumWriter<>(schema);DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(datumWriter);dataFileWriter.create(schema, file);dataFileWriter.append(person);dataFileWriter.close();System.out.println("Avro序列化完成");}
}

在这个示例中,我们使用Avro来定义消息的schema,并序列化Person对象。通过使用Avro,我们可以确保在分布式微服务中快速传输大量结构化数据。

5.3 持久化存储中的对象存储

在需要将对象存储到数据库或文件系统时,序列化的效率和数据压缩的能力尤为重要,尤其是在数据库中存储大规模对象时,数据存储和读取的效率直接影响到应用的响应速度和系统的扩展性。

优化方法:结合数据库索引与数据压缩
  • 使用Blob字段存储二进制数据:在关系型数据库中,通常将序列化后的对象作为Blob(二进制大对象)存储。为了提高性能,可以考虑将数据进行压缩处理,减少存储空间并提高读取速度。
  • 结合全文索引和压缩技术:对于需要频繁查询的对象数据,考虑使用索引或全文搜索引擎(如Elasticsearch)来增强检索性能。
import java.io.*;
import java.sql.*;public class DatabaseSerialization {public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {// 数据库连接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");PreparedStatement pstmt = conn.prepareStatement("INSERT INTO objects (data) VALUES (?)");// 创建对象并序列化Person person = new Person("John", 30);ByteArrayOutputStream byteStream = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(byteStream);out.writeObject(person);byte[] serializedData = byteStream.toByteArray();// 插入数据库pstmt.setBytes(1, serializedData);pstmt.executeUpdate();// 从数据库中取出并反序列化ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM objects");if (rs.next()) {byte[] data = rs.getBytes("data");ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));Person deserializedPerson = (Person) in.readObject();System.out.println("从数据库反序列化的对象:" + deserializedPerson);}conn.close();}
}

在这个示例中,我们将Person对象序列化后作为Blob类型存储在MySQL数据库中。对于数据库中的大量对象数据,使用压缩技术可以大幅度减小存储空间,并且结合合适的查询策略,可以提高存储和查询的效率。

5.4 缓存系统中的序列化

在大多数高性能系统中,缓存(如Redis、Memcached)常被用来存储临时数据。缓存系统中的数据通常需要高效序列化和反序列化,以保证快速访问和最小化内存占用。

优化方法:高效的序列化格式

使用适合缓存系统的高效序列化协议,如JSON、MsgPack、Protobuf等。Redis自带的String类型支持序列化数据,因此选择一个适合的序列化格式可以减少缓存存取的延迟。

import org.msgpack.core.MessagePack;
import org.msgpack.core.MessageBufferPacker;import java.io.IOException;public class MsgPackSerialization {public static void main(String[] args) throws IOException {Person person = new Person("John", 30);// 使用MsgPack进行序列化MessageBufferPacker packer = MessagePack.newDefaultPacker(System.out);packer.packString(person.getName());packer.packInt(person.getAge());packer.close();System.out.println("MsgPack序列化数据完成");}
}

在这个示例中,使用MsgPack进行序列化可以显著减少序列化后的数据大小,尤其适合高效的缓存和网络传输。

5.5 网络传输中的数据压缩

在进行网络通信时,尤其是带宽有限的场景中,压缩序列化数据是提高网络性能的一项重要技术。通过压缩,可以显著减少传输的数据量,加快数据传输速度,减少带宽消耗。

优化方法:结合序列化与压缩算法
  • 使用GZIPSnappyLZ4等高效压缩算法对序列化数据进行压缩,降低网络传输的负担。
  • 结合Protobuf等高效的序列化协议,这样可以在保证数据结构的紧凑性和反序列化速度的同时,进一步压缩数据。
import java.io.*;
import java.util.zip.GZIPOutputStream;public class CompressedNetworkTransfer {public static void main(String[] args) throws IOException {String data = "This is a sample data to be compressed and serialized";// 压缩数据ByteArrayOutputStream byteStream = new ByteArrayOutputStream();GZIPOutputStream gzip = new GZIPOutputStream(byteStream);gzip.write(data.getBytes());gzip.close();byte[] compressedData = byteStream.toByteArray();// 模拟网络传输System.out.println("压缩后的数据长度:" + compressedData.length);}
}

在这个示例中,我们通过GZIPOutputStream压缩数据,模拟了网络传输场景。在实际应用中,这种方法能有效减少网络带宽消耗并提高数据传输速度。

6. 总结

Java的对象序列化机制作为Java语言的重要特性之一,广泛应用于数据存储、网络通信、分布式系统等领域。然而,默认的序列化方式存在性能瓶颈,特别是在高并发、大数据量传输和存储的场景下。为了提高系统的效率和响应速度,开发者可以采取多种优化策略。

6.1 序列化优化的关键方法

  • 选择合适的序列化协议:如Protobuf、Avro、Thrift等,这些外部库在性能上优于Java原生的序列化方式,尤其适合在分布式系统和微服务架构中使用。
  • 对象图深度优化:通过减少不必要的递归序列化、使用transient字段等方式减少内存开销。
  • 数据压缩:对序列化后的数据进行压缩(如使用GZIP、Snappy等),可以显著降低存储空间和网络传输的开销,特别适用于大规模数据存储或高负载的网络通信。
  • 对象池与缓存:通过对象池来避免频繁的序列化和反序列化操作,提升性能;通过缓存机制存储序列化后的对象,减少重复计算。
  • 高效的序列化策略:在性能要求较高的场景中,结合并发优化(如异步序列化、批量处理)和高效的序列化框架,进一步减少性能瓶颈。

6.2 应用场景中的实践

  • 分布式系统与微服务架构:在服务之间的数据传输中,使用高效的序列化协议(如Protobuf、Avro)可以显著提升吞吐量,降低延迟。
  • 持久化存储:在数据库和文件系统中存储对象时,通过优化序列化和使用压缩算法,减少存储空间并提高读写效率。
  • 缓存系统:对于高并发访问的缓存数据,采用高效的序列化格式(如MsgPack、Protobuf)和压缩算法,提升系统的整体性能。
  • 网络传输:在网络通信中结合序列化与压缩技术,降低传输的数据量和提高网络带宽的利用率。

6.3 性能评估与监控

序列化优化需要在实际应用中进行性能测试和监控,以确保优化策略能有效提升系统性能。使用工具如JMH进行基准测试、性能分析工具(如VisualVM、YourKit)来识别瓶颈,并根据测试结果进行调整。

6.4 未来展望

随着系统复杂度和数据量的不断增加,序列化优化将成为开发中不可忽视的一个环节。未来,我们可以期待更加高效、更加智能的序列化技术和框架的出现,这些技术将帮助开发者更好地应对复杂系统中的性能挑战。

在实际应用中,开发者需要根据业务需求和技术栈的特点,灵活选择和结合不同的优化方法,不断提升系统的性能和可扩展性。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/19362.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wordpress资讯类网站整站打包

wordpress程序&#xff0c;内置了价值499元的模板.但是有了模板没有全自动采集相信大多数人都搞不懂&#xff0c;目录那么多&#xff0c;全靠原创几乎是不可能的事情&#xff0c;除非你是大公司&#xff0c;每人控制一个板块&#xff0c; 这套源码里面最有价值的应该是这个采集…

【深度解析】图解Deepseek-V3模型架构-混合专家模型(MoE)

一、引言 最近非常火爆的DeepSeek-V3模型&#xff0c;是一个包含6710亿总参数的强大混合专家模型&#xff08;MoE&#xff09;&#xff0c;其中每个token激活370亿参数。该模型在DeepSeek-V2验证有效的核心架构基础上&#xff0c;采用多头潜在注意力&#xff08;MLA&#xff0…

hive:分区>>静态分区,动态分区,混合分区

分区表 使用场景&#xff1a;数据量庞大且经常用来做查询的表 特点&#xff1a;将数据分别存储到不同的目录里 优点&#xff1a;避免全盘扫描&#xff0c;提高查询效率 分区的类型 它们的默认值分别是: false, strict, 要求至少有一个静态分区列&#xff0c;而 nonstr…

React进阶之React核心源码解析(一)

React核心源码解析 react 特点CPU卡顿IO 卡顿 新老 react 架构对比v15v16.8Scheduler 调度器Reconciler 协调器 React fiber原理更新dommount 构建过程 render阶段 — scheduler reconcilerreact源码解析react-domreact-dom/src/client/ReactDOMRoot.js react-reconcilerreact-…

ubuntu20.04连接airpods pro2

youtub视频解决方法&#xff1a;Setup your AirPods Pro with Linux (Ubuntu w/Mic fix) 重要步骤1&#xff0c; sudo apt-get update sudo apt-get install pulseaudio sudo apt-get upgrade pluseaudio重要步骤2&#xff0c; sudo vim /etc/bluetooth/main.confsudo /ect/…

sqli_labs_master Less-8 时间盲注,boolen盲注 获取数据库中的表、列

获取当前数据库名 import requestsdef inject_database(url):namemax_length20 # 假设数据库名称最大长度为20# ASCII范围&#xff1a;数字、字母、下划线&#xff08;_&#xff09;low{a: 97, z: 122, A: 65, Z: 90, 0: 48, 9: 57, _: 95}high{97: a, 122: z, 65: A, 90: Z,…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_ssl_init 函数

#if (NGX_OPENSSL)ngx_ssl_init(log); #endif objs/ngx_auto_config.h 中 #ifndef NGX_OPENSSL #define NGX_OPENSSL 1 #endif 所以这个条件编译成立 NGX_OPENSSL 是一个宏定义&#xff0c;用于控制与 OpenSSL 相关的功能是否被启用 若用户通过./configure参数&#xff08;如-…

常用架构图:业务架构、产品架构、系统架构、数据架构、技术架构、应用架构、功能架构及信息架构

文章目录 引言常见的架构图I 业务架构图-案例模块功能说明1. 用户界面层 (UI)2. 应用服务层3. 数据管理层4. 基础设施层业务流程图示例技术实现II 功能架构图 -案例功能模块说明1. 船舶监控模块2. 报警管理模块3. 应急响应模块4. 通信管理模块5. 数据分析模块数据管理层基础设施…

Redis 09章——哨兵(sentinel)

一、是什么 吹哨人巡查监控后台master主机是否故障&#xff0c;如果故障了根据$\textcolor{red}{投票数}$自动将某一个从库转换为新主库&#xff0c;继续对外服务作用&#xff1a;俗称无人值守运维官网理论&#xff1a;High availability with Redis Sentinel | Docs 二、能干…

WEB入门

1.了解什么是WEB 2.了解什么是WEB前端 3.学习和掌握开发环境的搭建 4.网页开发基础 1.什么是WEB 1946年&#xff0c;有一个发明了人类史上第一台完整体系的计算机 时间进展到1989年&#xff0c;实验室有一个研发人员 TimBernersLee&#xff08;提姆博纳斯李&#xff09;开…

【若依免登录】登录状态已过期,您可以继续留在该页面,或者重新登录

【问题】 【问题背景】 在实现若依的免登录出现的问题。前面已经做的操作 前端 第一步&#xff1a;views目录下面存在需要免登录的页面 第二步&#xff1a;在ruoyi-ui\src\router 的 index.js 的 constantRoutes &#xff08;公共路由方&#xff09;中 配置需要免登录的页面位…

JUC并发-4.wait和notify以及Atomic原理

大纲 1.wait()与notify()实现一个简易的内存队列 2.wait()与notify()的底层原理 3.分布式存储系统NameNode机制介绍 4.分布式存储系统的edits log机制介绍 5.分布式存储系统的NameNode实现 6.分布式存储系统的创建目录功能的实现 7.edits log的全局txid机制和双缓冲机制…

Jasper AI技术浅析(二):语言模型

Jasper AI 的核心语言模型是基于 OpenAI 的 GPT-4(Generative Pre-trained Transformer 4)构建的。GPT-4 是一种生成式预训练语言模型,利用深度学习技术,特别是 Transformer 架构,来理解和生成自然语言。 1. GPT-4 的基本原理 1.1 Transformer 架构 GPT-4 基于 Transfo…

(arxiv2411) CARE Transformer

作者提出了两个问题&#xff0c;问题 1&#xff1a;堆叠是充分利用局部归纳偏差和长距离信息优势的最佳方法吗&#xff1f; 问题 2&#xff1a;是否有可能同时提高线性视觉 Transformer 的效率和准确性&#xff1f; 为了解决这两个问题&#xff0c;作者提出了一种 deCoupled du…

RISC-V平台编译 state-thread x264 ffmpeg zlog

1.state-threads 源码下来之后 直接 make linux-debug 目录下生成了对应的.a 和 .h文件 gcc test.c -o test -l st -L . #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/socket.h&g…

DeepSeek笔记(二):DeepSeek局域网访问

如果有多台电脑&#xff0c;可以通过远程访问&#xff0c;实现在局域网环境下多台电脑共享使用DeepSeek模型。在本笔记中&#xff0c;首先介绍设置局域网多台电脑访问DeepSeek-R1模型。 一、启动Ollama局域网访问 1.配置环境变量 此处本人的操作系统是Windows11&#xff0c;…

2025年二级建造师报名流程图解

2025年二级建造师报名时间&#xff01;附报名流程&#xff01; ⏰️已公布25年二建考试时间的省份如下&#xff1a; ️4月19日、20日考试的城市有&#xff1a;贵州 ️5月10日、11日考试的城市有&#xff1a;湖北、陕西、宁夏、甘肃、福建、浙江、江西、黑龙江、河南、湖南、…

Android的Activity生命周期知识点总结,详情

一. Activity生命周期 1.1 返回栈知识点 二. Activity状态 2.1 启动状态 2.2 运行状态 2.3 暂停状态 2.4 停止状态 2.5 销毁状态 三. Activity生存期 3.1 回调方法 3.2 生存期 四. 体验Activity的生命周期 五. Activity被回收办法 引言&#xff1a; 掌握Acti…

frp-tool,客户端frp命令行工具

在日常开发和运维过程中&#xff0c;端口转发和配置管理是常见的需求。 如果有自己一台服务器&#xff0c;并且已经开放好端口&#xff0c;配置好token后&#xff0c;这个工具一定能帮到你。 今天给大家推荐一款非常好用的frpc命令行工具&#xff0c;它是一个用Python编写的命令…

netcore https配置

一、生成证书 1. 安装 OpenSSL 如果尚未安装 OpenSSL&#xff0c;可以通过以下命令安装&#xff1a;Ubuntu/Debian:sudo apt update sudo apt install openssl CentOS/RHEL:sudo yum install openssl 2. 生成私钥 使用以下命令生成私钥文件&#xff08;private.key&#xff09…